题解 P4938 【War1】
上一篇题解还是讲得过于简单了吧...
稍微详细一点。
每个点可以向其他点传输能量,显然是网络流。
同时,不能间接传输能量,
那么考虑拆点,将一个点拆成入点和出点,点与点之间只有入点能向出点传输能量。
这样就避免了已经被传输到出点的能量再被传到别处去。
然后就是套路,源点向第
输出方案的话,只要看看每条边上的剩余容量与原来差了多少,就知道起点向终点传输了多少能量了。
代码可以参考
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using std::queue;
const int N=1005,M=500005;
const int S=1003,T=1004;
int n,m;
int head[N],cur[N],level[N];
struct Edge
{
int next,to,w,w0;
};
Edge E[M];
void __add(int u,int v,int w)
{
static int tot=-1;
E[++tot].next=head[u];
E[tot].to=v;
E[tot].w=E[tot].w0=w;
head[u]=tot;
}
void add(int u,int v,int w)
{
__add(u,v,w);
__add(v,u,0);
}
bool bfs(int S,int T)
{
memset(level,0x00,sizeof(level));
queue<int> q;
q.push(S);
level[S]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];~i;i=E[i].next)
{
int v=E[i].to;
if(E[i].w==0||level[v]!=0)continue;
level[v]=level[u]+1;
q.push(v);
}
}
return level[T];
}
int dfs(int u,int flow,int T)
{
if(u==T||flow==0)return flow;
int res=0;
for(int i=cur[u];~i;cur[u]=i=E[i].next)
{
int v=E[i].to;
if(level[v]==level[u]+1&&E[i].w!=0)
{
int f=dfs(v,std::min(flow,E[i].w),T);
if(f!=0)
{
res+=f;
flow-=f;
E[i].w-=f;
E[i^1].w+=f;
if(flow==0)break;
}
}
}
return res;
}
int dinic(int S,int T)
{
int res=0;
while(bfs(S,T))
{
memcpy(cur,head,sizeof(head));
res+=dfs(S,0x7fffffff,T);
}
return res;
}
int in_id(int x)
{
return x;
}
int out_id(int x)
{
return x+n;
}
int ans[N][N];
int main()
{
memset(head,0xff,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
add(S,in_id(i),x);
add(in_id(i),out_id(i),0x3fffffff);
}
int sum=0;
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
sum+=x;
add(out_id(i),T,x);
}
for(int i=0;i<m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(in_id(u),out_id(v),0x3fffffff);
add(in_id(v),out_id(u),0x3fffffff);
}
if(dinic(S,T)!=sum)
{
puts("NO");
return 0;
}
puts("YES");
for(int u=1;u<=n;++u)
{
for(int i=head[u];~i;i=E[i].next)
{
int v=E[i].to;
if(v<=n)continue;
if(v>n*2)continue;
v-=n;
ans[u][v]+=E[i].w0-E[i].w;
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
printf("%d ",ans[i][j]);
}
putchar('\n');
}
}