http://acm.hdu.edu.cn/showproblem.php?pid=4975
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Case #1: So simple! Case #2: So naive! Case #3: So young!
/**
hdu 4975 网络流及‘删边法’判是否为唯一流
题目大意:给定一个n*m的棋盘,给出每行的和以及每列的和,问是否可以确定出该棋盘(唯一,多解or无解)
解题思路:源点与各行建边,流量行和,汇点与各列建边,流量列和,行和列相互建边,流量9。跑网络流,满流有解;
至于判断多解,我们对残余网络进行dfs判断是否能找出边数大于2的非零环,若残余网络上有多个点构成一
个环,那么流量可在这个环上调整,某条边上多余的流量可以被环上的其他的边弥补回来。所以如果残余网
络上存在一个边数大于2的环,那么问题则是多解。
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int oo=1e9;
const int mn=1015;
const int mm=505*505*3;
///=========最大流=========
int node,src,dest;
int ver[mm],flow[mm],nex[mm];
int head[mn],ip,work[mn],dis[mn],q[mn];
void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v,int c)
{
ver[ip]=v,flow[ip]=c,nex[ip]=head[u],head[u]=ip++;
ver[ip]=u,flow[ip]=0,nex[ip]=head[v],head[v]=ip++;
}
bool Dinic_bfs()
{
int i,u,v,l,r=0;
for(i=0; i<node; i++)dis[i]=-1;
dis[q[r++]=src]=0;
for(l=0; l<r; l++)
{
for(i=head[u=q[l]]; i!=-1; i=nex[i])
{
if(flow[i]&&dis[v=ver[i]]<0)
{
dis[q[r++]=v]=dis[u]+1;
if(v==dest)return 1;
}
}
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp; i>=0; i=nex[i])
{
if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
return tmp;
}
}
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0; i<node; i++)work[i]=head[i];
while(delta=Dinic_dfs(src,oo))ret+=delta;
}
return ret;
}
///============判环=============
int walked[mn];
bool dfs(int u,int pre)
{
int biu=-1;
walked[u]=true;
for(int i=head[u]; i!=-1; i=nex[i])
{
int v=ver[i];
if(v==pre)continue;
if(flow[i]>0)
{
if(walked[v])return true;
if(dfs(v,u))return true;
}
if(biu==-1)head[u]=nex[i];
else nex[biu]=nex[i];
biu=i;
}
walked[u]=false;
return false;
}
bool judge()
{
memset(walked,false,sizeof(walked));
for(int i=1; i<=node; i++)
{
if(dfs(i,-1))return true;
}
return false;
}
///==============================
int n,m,c1[mn],c2[mn];
int main()
{
int T,tt=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int sum1=0,sum2=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&c1[i]);
sum1+=c1[i];
}
for(int i=1; i<=m; i++)walked[mn];
{
scanf("%d",&c2[i]);
sum2+=c2[i];
}
printf("Case #%d: ",++tt);
if(sum1!=sum2)
{
puts("So naive!");
continue;
}
///====建边====
prepare(n+m+2,0,n+m+1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
addedge(i,j+n,9);
}
}
for(int i=1; i<=n; i++)
{
addedge(src,i,c1[i]);
}
for(int i=1; i<=m; i++)
{
addedge(i+n,dest,c2[i]);
}
///============
if(Dinic_flow()!=sum1)
{
puts("So naive!");
}
else
{
if(judge())
puts("So young!");
else
puts("So simple!");
}
}
return 0;
}
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Case #1: So simple! Case #2: So naive! Case #3: So young!
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/lvshubao1314/article/details/47300391