【BZOJ】【P1475】【方格取数】【题解】【最小割】

来源:互联网 发布:网络编程。tcp udp视频 编辑:程序博客网 时间:2024/05/16 04:40

传送门:www.lydsy.com:808/JudgeOnline/problem.php?id=1475

太弱了……想了居然想了好几天……然后faebdc 10s就破了此题Orz

黑白染色,s->黑 cap=权值 白->t cap=权值 互斥的连边INF,跑最小割然后减

Code:

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<climits>#include<queue>using namespace std;const int maxn=910;struct edge{int u,v,cap,flow;edge(int _u=0,int _v=0,int _cap=0,int _flow=0):u(_u),v(_v),cap(_cap),flow(_flow){}};vector<edge>edges;vector<int>G[maxn];int cur[maxn],vis[maxn];void add(int u,int v,int cap){edges.push_back(edge(u,v,cap,0));G[u].push_back(edges.size()-1);edges.push_back(edge(v,u,0,0));G[v].push_back(edges.size()-1);}int d[maxn],s,t;bool bfs(){memset(vis,0,sizeof(vis));queue<int>q;q.push(s);vis[s]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<G[u].size();i++){edge e=edges[G[u][i]];if(e.cap>e.flow&&!vis[e.v]){d[e.v]=d[u]+1;vis[e.v]=1;q.push(e.v);}}}return vis[t];}int dfs(int u,int a){int flow=0,f;if(u==t||!a)return a;for(int &i=cur[u];i<G[u].size();i++){edge e=edges[G[u][i]];if(d[e.v]==d[u]+1&&(f=dfs(e.v,min(a,e.cap-e.flow)))>0){edges[G[u][i]].flow+=f;edges[G[u][i]^1].flow-=f;flow+=f;a-=f;if(!a)break;}}return flow;}int Dinic(){int flow=0;while(bfs()){int x=0;do{flow+=x;memset(cur,0,sizeof(cur));}while(x=dfs(s,INT_MAX));}return flow;}int n,tot;int hash[31][31];int a[31][31];int sum=0;const int dx[4]={0,1,0,-1};const int dy[4]={1,0,-1,0};int main(){cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>a[i][j];hash[i][j]=++tot;sum+=a[i][j];}s=0;t=tot+1;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if((i+j+1)&1)add(s,hash[i][j],a[i][j]);elseadd(hash[i][j],t,a[i][j]);if((i+j+1)&1)for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(x<1||x>n||y<1||y>n)continue;add(hash[i][j],hash[x][y],INT_MAX);}}int deb=0;if(deb)for(int i=0;i<edges.size();i++){edge e=edges[i];if(i%2==0)printf("%d -> %d cap:%d\n",e.u,e.v,e.cap);}cout<<sum-Dinic()<<endl;return 0;}


0 0
原创粉丝点击