您的位置:首页 > 理论基础 > 计算机网络

hdu 4975 A simple Gaussian elimination problem. 2014多校十 网络流

2014-08-22 22:54 471 查看
题目链接:hdu 4975

hdu 4888很类似,只不过这里的上限都是9,且不需要输出唯一的矩阵

只不过这道题会卡找环的过程。调整行列之间的流量可以优化,不难发现行列之间的流量可以是该行和,该列和,以及9的最小值,这样调整了之后就能使得找环省去无用的操作。

/******************************************************
* File Name:   4975.cpp
* Author:      kojimai
* Creater Time:2014年08月21日 星期四 20时06分03秒
******************************************************/
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 505
int row[FFF],col[FFF],n,m;
struct node
{
int u,v,f,next;
}p[510010];
int first[FFF*2],e,cur[FFF*2],dis[FFF*2],que[FFF*4];
bool bfs(int s,int t)//找增广路径
{
memset(dis,-1,sizeof(dis));
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int now=q.front();q.pop();
for(int k=first[now];~k;k=p[k].next)
{
if(p[k].f>0&&dis[p[k].v]==-1)
{
dis[p[k].v]=dis[now]+1;
if(p[k].v==t)
return true;
q.push(p[k].v);
}
}
}
return false;
}

int dinic(int s,int t)//dinic求最大流
{
//cout<<"s="<<s<<" t="<<t<<endl;
int ans=0;
while(bfs(s,t))
{
memcpy(cur,first,sizeof(first));
int now=s,tail=0;
while(true)
{
int k;
if(now==t)
{
int flow=23333333,fir;
for(int i=0;i<tail;i++)
{
if(p[que[i]].f<flow)
{
fir=i;
flow=p[que[i]].f;
}
}
for(int i=0;i<tail;i++)
{
p[que[i]].f-=flow;
p[que[i]^1].f+=flow;
}
ans+=flow;
tail=fir;
now=p[que[fir]].u;
}
for(k=cur[now];~k;cur[now]=k=p[k].next)
{
if(p[k].f&&dis[now]+1==dis[p[k].v])
break;
}
if(cur[now]!=-1)
{
que[tail++]=cur[now];
now=p[cur[now]].v;
}
else
{
if(tail==0)
break;
dis[now]=-1;
now=p[que[--tail]].u;
}
}
}
return ans;
}

bool vis[FFF*2];
bool dfs(int s,int last)//找环
{
for(int k=first[s];~k;k=p[k].next)
{
if(p[k].v==last)continue;
if(p[k].f)
{
if(vis[p[k].v])return true;
vis[p[k].v]=true;
if(dfs(p[k].v,s))return true;
vis[p[k].v]=false;
}
}
return false;
}

void addedge(int u,int v,int c)
{
p[e].u=u;p[e].v=v;p[e].f=c;p[e].next=first[u];first[u]=e++;
p[e].v=u;p[e].u=v;p[e].f=0;p[e].next=first[v];first[v]=e++;
}
int main()
{
//freopen("out.out","w",stdout);
int keng,Cas=1;
scanf("%d",&keng);
while(keng--)
{
bool flag=true;
scanf("%d%d",&n,&m);
int allr=0,allc=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&row[i]);
if(row[i]<0||row[i]>9*m)
flag=false;
allr+=row[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d",&col[i]);
if(col[i]<0||col[i]>9*n)
flag=false;
allc+=col[i];
}
printf("Case #%d: ",Cas++);
//cout<<"flag="<<flag<<' '<<endl;
if(!flag||allr!=allc)
printf("So naive!\n");
else
{
//cout<<"fuck"<<endl;
e=0;
memset(first,-1,sizeof(first));
for(int i=1;i<=n;i++)
addedge(0,i,row[i]);
for(int i=1;i<=m;i++)
addedge(i+n,n+m+1,col[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
addedge(i,j+n,min(9,min(row[i],col[j])));
int sum=dinic(0,n+m+1);
//cout<<"sum="<<sum<<endl;
if(sum!=allc)
printf("So naive!\n");
else
{
memset(vis,false,sizeof(vis));
flag=false;
if(sum!=0)
for(int i=1;i<=n&&!flag;i++)
{
//cout<<"i="<<i<<endl;
if(!vis[i]&&row[i])
flag=dfs(i,-1);
}
if(flag)
printf("So young!\n");
else
printf("So simple!\n");
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: