网络流_hdu3338Kakuro Extension (神奇最大流 Dinic)

来源:互联网 发布:工艺流程图画图软件 编辑:程序博客网 时间:2024/06/16 02:33

题意:

        给一个表格的横纵和,用1~9去填,数字可重复,求一种解决方案。

       

        建图思路:

        从空白格任取一个数,假定这个数所在为i行j列。则这个数的数值既被包括在行之和中,也被包括在列之中。那么我们可以采用行进列出的思想。从原点连向行之和节点,从列之和节点连向汇点。 中间就通过任意的空白格节点将行之和与列之和连接起来。题目要求是1~9为有上下限的最大流。由于此题是求和。我们可以以0~8代替1~9。相应的行与列之和需减去代替的个数。这样就化简成了普通的网络流。

        然而,这样其实还存在一个问题,实际上,每一个空白格节点左右各只有一条边,流进与流出都是相等的,那么这个节点其实可以省略掉。所以我们直接把节点化成了一条边。如果这个数属于第i行第j列(注意这里的i行j列不是原图中的,因为一行可能会拆成多个点),那么我们就把第i行的节点与第j列的节点之间连一条容量为8的边。所输出的答案也就是这条边的流量。


附代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>using namespace std;const int maxn=10010;#define INF 1000000000#define MIN(a,b) a<b?a:bstruct EDGE{int u,v,flow,next;}edge[10*maxn];int mark[maxn],head[maxn];int cnt,src,des;int col[maxn],row[maxn];int map[105][105][2];int out[105][105];int pointnum=0,rownum=0,colnum=0;void addedgeSub(int u,int v,int w){edge[cnt].u=u;edge[cnt].v=v;edge[cnt].flow=w;edge[cnt].next=head[u];head[u]=cnt++;}void addedge(int u,int v,int w){addedgeSub(u,v,w);addedgeSub(v,u,0);}int process(char *s,int l,int r){if(s[l]=='X')return -1;return 100*(s[l]-'0')+10*(s[l+1]-'0')+s[l+2]-'0';}void init(){cnt=0;memset(head,-1,sizeof(head));memset(row,0,sizeof(row));memset(col,0,sizeof(col));memset(out,-1,sizeof(out));}void output(int n,int m){for(int i=0;i<n;i++){for(int j=0;j<m;j++){printf("(%d,%d) ",map[i][j][0],map[i][j][1]);}printf("\n");}}void input(int n,int m){rownum=0,colnum=0;char str[10];init();int len=0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%s",str);if(strcmp(str,".......")==0){map[i][j][0]=map[i][j-1][0];map[i][j][1]=map[i-1][j][1];int x=map[i][j][0];int y=map[i][j][1];row[x]--;col[y]--;out[i][j]=0;continue;}int num1=process(str,0,2);int num2=process(str,4,6);if(num2!=-1)row[++rownum]=num2,map[i][j][0]=rownum;if(num1!=-1)col[++colnum]=num1,map[i][j][1]=colnum;}}des=rownum+colnum+1;src=0;for(int i=1;i<=rownum;i++)addedge(src,i,row[i]);for(int i=1;i<=colnum;i++)addedge(rownum+i,des,col[i]);for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(out[i][j]!=-1){addedge(map[i][j][0],map[i][j][1]+rownum,8);out[i][j]=cnt-2;}}}}bool bfs(int x){memset(mark,-1,sizeof(mark));mark[x]=1;queue<int>q;q.push(x);while(!q.empty()){int k=q.front();q.pop();for(int i=head[k];i!=-1;i=edge[i].next){int v=edge[i].v;if(mark[v]==-1&&edge[i].flow){mark[v]=mark[k]+1;q.push(v);}}}return mark[des]!=-1;}int dfs(int x,int delta){int cost=0,min;if(x==des)return delta;for(int i=head[x];i!=-1;i=edge[i].next){int v=edge[i].v;if(mark[v]==mark[x]+1&&edge[i].flow){min=dfs(v,MIN(edge[i].flow,delta-cost));if(min>0){edge[i].flow-=min;edge[i^1].flow+=min;cost+=min;if(cost==delta)break;}elsemark[v]=-1;}}return cost;}void print(int n,int m){for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(out[i][j]==-1)printf("_");else {int id=out[i][j];printf("%d",8-edge[id].flow+1);}if(j!=m-1)printf(" ");}printf("\n");}}void Dinic(){int ans=0;while(bfs(src))ans+=dfs(src,INF);}int main(){int n,m;char str[10];while(~scanf("%d%d",&n,&m)){input(n,m);Dinic();print(n,m);}return 0;}


0 0
原创粉丝点击