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!
题目意思很简单:就是给出一个矩阵的行和和列和,矩阵中的每个元素都是0-9,问原矩阵是否存在,是否唯一;
分析:网络流求解,如果最大流=所有元素的和则有解;利用残留网络判断是否唯一,方法有两种,第一种是深搜看看是否存在正边权的环,至少3个点构成的环,第二种是用矩阵dp,假如某行的i列元素<9,j列元素>0,而另一行的i列元素>0,j列元素<9,那么答案不是唯一的,因为主对角线的 两个元素可以增大1,而副对角线的两个元素可以减小1,可以明显看出有多个答案;
比赛时的程序:
#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"math.h"
#define M 1900
#define eps 1e-10
#define inf 100000000
using namespace std;
struct node
{
int u,v,w,next;
}edge[600000];
int t,head[M],row[M],col[M],q[M],dis[M],work[M],use[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
edge[t].u=u;
edge[t].v=v;
edge[t].w=w;
edge[t].next=head[u];
head[u]=t++;
edge[t].u=v;
edge[t].v=u;
edge[t].w=0;
edge[t].next=head[v];
head[v]=t++;
}
int bfs(int S,int T)
{
int rear=0;
memset(dis,-1,sizeof(dis));
dis[S]=0;
q[rear++]=S;
for(int i=0;i<rear;i++)
{
for(int j=head[q[i]];j!=-1;j=edge[j].next)
{
int v=edge[j].v;
if(edge[j].w&&dis[v]==-1)
{
dis[v]=dis[q[i]]+1;
q[rear++]=v;
if(v==T)
return 1;
}
}
}
return 0;
}
int dfs(int cur,int a,int T)
{
if(cur==T)
return a;
for(int &i=work[cur];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].w&&dis[v]==dis[cur]+1)
{
int tt=dfs(v,min(a,edge[i].w),T);
if(tt)
{
edge[i].w-=tt;
edge[i^1].w+=tt;
return tt;
}
}
}
return 0;
}
int Dinic(int S,int T)
{
int ans=0;
while(bfs(S,T))
{
memcpy(work,head,sizeof(head));
while(int tt=dfs(S,inf,T))
ans+=tt;
}
return ans;
}
int DFS(int u,int f)
{
use[u]=1;
for(int &i=work[u];i!=-1;i=edge[i].next)//加&和复制的work数组
{
int v=edge[i].v;
if(edge[i].w&&v!=f)
{
if(use[v])
return 1;
if(DFS(v,u))
return 1;
}
}
use[u]=0;
return 0;
}
int judge(int n,int m)
{
memset(use,0,sizeof(use));
memcpy(work,head,sizeof(head));//当初加了个这东西就莫名其妙的过了,并且很省时
for(int i=1;i<=n;i++)
{
if(DFS(i,i))
return 1;
}
return 0;
}
int main()
{
int n,m,i,j,kk=1;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int r=0,c=0;
for(i=1;i<=n;i++)
{
scanf("%d",&row[i]);
r+=row[i];
}
for(j=1;j<=m;j++)
{
scanf("%d",&col[j]);
c+=col[j];
}
printf("Case #%d: ",kk++);
if(r!=c)
{
printf("So naive!\n");
continue;
}
int flag=0;
for(i=1;i<=n;i++)
{
if(m*9<row[i])
flag++;
}
for(i=1;i<=m;i++)
{
if(n*9<col[i])
flag++;
}
if(flag)
{
printf("So naive!\n");
continue;
}
init();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
add(i,n+j,9);
}
}
for(i=1;i<=n;i++)
add(0,i,row[i]);
for(j=1;j<=m;j++)
add(j+n,m+n+1,col[j]);
int ans=Dinic(0,m+n+1);
if(ans<r)
{
printf("So naive!\n");
continue;
}
if(judge(n,m))
{
printf("So young!\n");
continue;
}
printf("So simple!\n");
}
return 0;
}
#include"stdio.h"
#include"string.h"
#include"iostream"
#include"map"
#include"string"
#include"queue"
#include"stdlib.h"
#include"math.h"
#define M 1900
#define eps 1e-10
#define inf 1000000000
#define mod 2333333
using namespace std;
struct node
{
int u,v,w,next;
}edge[600000];
int t,head[M],work[M],use[M],dis[M],mp[555][555],G[555][555],row[555],col[555];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
edge[t].u=u;
edge[t].v=v;
edge[t].w=w;
edge[t].next=head[u];
head[u]=t++;
edge[t].u=v;
edge[t].v=u;
edge[t].w=0;
edge[t].next=head[v];
head[v]=t++;
}
int bfs(int S,int T)
{
memset(dis,-1,sizeof(dis));
queue<int>q;
dis[S]=0;
q.push(S);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].w&&dis[v]==-1)
{
dis[v]=dis[u]+1;
q.push(v);
if(v==T)
return 1;
}
}
}
return 0;
}
int dfs(int cur,int a,int T)
{
if(cur==T)return a;
for(int &i=work[cur];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].w&&dis[v]==dis[cur]+1)
{
int tt=dfs(v,min(edge[i].w,a),T);
if(tt)
{
edge[i].w-=tt;
edge[i^1].w+=tt;
return tt;
}
}
}
return 0;
}
int Dinic(int S,int T)
{
int ans=0;
while(bfs(S,T))
{
memcpy(work,head,sizeof(head));
while(int tt=dfs(S,inf,T))
ans+=tt;
}
return ans;
}
int judge(int n,int m)
{
int k=0,i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
G[i][j]=edge[k^1].w;
k+=2;
}
}
memset(mp,0,sizeof(mp));
for(i=1;i<=n;i++)
{
if(row[i]==0||row[i]==9*m)continue;
for(j=1;j<=m;j++)
{
if(col[j]==0||col[j]==9*n)continue;
for(k=j+1;k<=m;k++)
{
int f1=0,f2=0;
if(G[i][j]<9&&G[i][k]>0)
{
if(mp[k][j])
return 1;
f1++;
}
if(G[i][j]>0&&G[i][k]<9)
{
if(mp[j][k])
return 1;
f2++;
}
if(f1)mp[j][k]=1;
if(f2)mp[k][j]=1;
}
}
}
return 0;
}
int main()
{
int T,m,n,kk=1,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int r=0;
for(i=1;i<=n;i++)
{
scanf("%d",&row[i]);
r+=row[i];
}
int c=0;
for(j=1;j<=m;j++)
{
scanf("%d",&col[j]);
c+=col[j];
}
printf("Case #%d: ",kk++);
if(c!=r)
{
printf("So naive!\n");
continue;
}
int flag=0;
for(i=1;i<=n;i++)
if(9*m<row[i])
flag++;
for(j=1;j<=m;j++)
if(9*n<col[j])
flag++;
if(flag)
{
printf("So naive!\n");
continue;
}
init();
int st=0;
int sd=n+m+1;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
add(i,j+n,9);
}
}
for(i=1;i<=n;i++)
add(st,i,row[i]);
for(j=1;j<=m;j++)
add(j+n,sd,col[j]);
int ans=Dinic(st,sd);
if(ans!=r)
{
printf("So naive!\n");
continue;
}
if(judge(n,m))
{
printf("So young!\n");
continue;
}
printf("So simple!\n");
}
return 0;
}
hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)
原文:http://blog.csdn.net/mypsq/article/details/38756921