洛谷P3355
程序员文章站
2022-06-08 14:26:11
...
最大流与最小割之间的转换,题目做法类似于P2774方格取数
最多放多少骑士==最少拿走多少
观察图片不难发现:黄色的不能攻击黄色的,红色同理 这一点非常重要,考虑到这一点,就可以把点分为两类,一类连源点,一类连汇点,否则的话很难建图;
那么不难想到二分图匹配
这样就转化成了二分图最小定点覆盖
而二分图最小顶点覆盖==二分图最大匹配。证明可以看这里
从S向红色连边(权重为1),从红色向能攻击到的黄色连边(权重为INF),从黄色向T连边(权重为1)
跑最大流
另一个不错的题解:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
struct edge{
int to,cap,rev;
};
const int N=4e4+100;
vector<edge>G[N];
int level[N],iter[N];
void addedge(int from,int to,int cap)
{
G[from].push_back(edge{to,cap,(int)G[to].size()});
G[to].push_back(edge{from,0,(int)G[from].size()-1});//反向容量为0!!
}
void bfs(int s)
{
memset(level,-1,sizeof(level));
queue<int>que;
level[s]=0;que.push(s);
while(!que.empty()){
int t=que.front();que.pop();
for(int i=0;i<G[t].size();i++){
edge e=G[t][i];
if(e.cap>0&&level[e.to]<0){
level[e.to]=level[t]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f)
{
if(v==t)return f;
for(int&i=iter[v];i<G[v].size();i++){//注意传引用!
edge&e=G[v][i];
if(e.cap>0&&level[v]<level[e.to]){
int d=dfs(e.to,t,min(f,e.cap));
if(d>0){
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;//不要漏了这个,很多时候可能是无法增广的
}
int maxflow(int s,int t){
int flow=0;
for(;;){
bfs(s);
if(level[t]<0)return flow;
memset(iter,0,sizeof(iter));
int f;
while(f=dfs(s,t,0x7f7f7f7f))
flow+=f;
}
}
int n,m;
int get(int x,int y)
{
return (y-1)*n+x;
}
pair<int,int> getf(int x)
{
int i=x%n;int j=(x-i)/n+1;
return make_pair(i,j);
}
int main()
{
int i,j,k,a,b;
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) {
k = get(i, j);
//addedge(0, k, 1);
if ((i + j) & 1) {
addedge(k, 40050, 1);
} else {
addedge(0, k, 1);
}
}
for(i=1;i<=m;i++){
scanf("%d%d",&a,&b);
if((a+b)&1){
k=get(a,b);G[k].pop_back();
}
else{
k=get(a,b);j=G[k][0].rev;
G[0][j].cap=0;
}
}
int move[8][2]={2,1,1,2,2,-1,1,-2,-1,2,-2,1,-2,-1,-1,-2};
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if((i+j)&1)continue;
for(k=0;k<8;k++){
if(i+move[k][0]>0&&i+move[k][0]<=n&&j+move[k][1]>0&&j+move[k][1]<=n){//注意这里的i,j,k不要弄混了!!!!
a=get(i,j);b=get(i+move[k][0],j+move[k][1]);
addedge(a,b,1);
}
}
}
cout<<n*n-maxflow(0,40050)-m<<endl;
return 0;
}
上一篇: 重启MySQL的正确方法_MySQL
下一篇: centos7搭建zabbix5.0