CodeForces 546E - Soldier and Traveling(最大流+输出边流量)

题目链接:click here~~

题目大意】:给定一些城市里面原先状态的士兵数目,和某些城市之间的联通关系,求能否达到最终状态。

解题思路】做完这套题,感觉这道题是五个题里最有质量的题了,搞了差不多一天半的时间,开始很难想到构图,想到了是最大流之后,又卡在了输出流量上,w(゚Д゚)w,还是这类题做的太少,~~~~(>_<)~~~~!首先比较很难构想到最大流,但是抓住题目关键,仔细想想也不难,好,想到了是构造最大流,那么接下来难点是建源点,汇点,剩下的就是套模板了,弱弱的献上代码,欢迎各位指正~~

Sample Input

Input
4 4
1 2 6 3
3 5 3 1
1 2
2 3
3 4
4 2
Output
YES
1 0 0 0 
2 0 0 0 
0 5 1 0 
0 0 2 1 
Input
2 0
1 2
2 1
Output
NO
附图一张:

CodeForces 546E - Soldier and Traveling(最大流+输出边流量)_第1张图片

代码:

/*
Author :HRW
思路:建图,最大流,注意反向边,容量,流量为0
      建源点,汇点,
      最后输出路径保证每条边的流量都要输出,只需之前统计有哪些边流量发生了变化
*/
#include <bits/stdc++.h>
using namespace std;
const int N=305;
const int inf=0x3f3f3f3f;
struct Edge
{
    int from,to,cap,flow;//顶点-顶点,容量,流量
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
};
vector <Edge> edges;
vector <int > G[N];
int d[N],cur[N],num[N][N];
int n,m,S,T,a,b,C;
bool vis[N],flag;
void init()
{
    for(int i=0; i<=n; i++)
    {
        G[i].clear(),edges.clear();
    }
}
void add_edge(int from,int to,int cap)
{
    edges.push_back(Edge(from,to,cap,0));
    edges.push_back(Edge(to,from,0,0));
    C=edges.size();
    G[from].push_back(C-2);
    G[to].push_back(C-1);
}
bool bfs(int s,int t)
{
    memset(vis,false,sizeof(vis));
    queue <int >Q;
    d[s]=0;
    Q.push(s);
    vis[s]=true;
    while(!Q.empty())
    {
        int q=Q.front();
        Q.pop();
        for(int i=0; i<G[q].size(); i++)//一定要注意G[q].size(),写成G[i].size(),样例竟然过,导致RE一页!
        {
            Edge &e=edges[G[q][i]];
            if(!vis[e.to]&&e.cap>e.flow)
            {
                d[e.to]=d[q]+1;
                Q.push(e.to);
                vis[e.to]=true;
            }
        }
    }
    return vis[T];
}
int dfs(int s,int k)
{
    if(s==T||k==0) return k;
    int f,flow=0;
    for(int &i=cur[s]; i<G[s].size(); i++)
    {
        Edge &e=edges[G[s][i]];
        if(d[e.to]==d[s]+1&&(f=dfs(e.to,min(k,e.cap-e.flow)))>0)
        {
            e.flow+=f;
            edges[G[s][i]^1].flow-=f;
            flow+=f;
            k-=f;
            if(k==0) break;
        }
    }
    return flow;
}
int max_flow(int s,int t)
{
    int flow=0;
    while(bfs(s,t))
    {
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,inf);
    }
    return flow;
}
int main()
{
    init();
    scanf("%d%d",&n,&m);
    S=0,T=2*n+1;
    int u,v,a,b,suma=0,sumb=0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a);
        suma+=a;
        add_edge(S,i,a);
        add_edge(i,i+n,inf);
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&b);
        sumb+=b;
        add_edge(i+n,T,b);
    }
    if(suma!=sumb)
    {
        puts("NO");
        return 0;
    }
    while(m--)
    {
        scanf("%d%d",&v,&u);
        add_edge(v,u+n,inf);
        add_edge(u,v+n,inf);
    }
    int ans=max_flow(S,T);
    //cout<<ans<<endl;
    if(suma!=ans)
    {
        puts("NO");
    }
    else
    {
        puts("YES");
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<G[i].size(); j++)
            {
                Edge&e=edges[G[i][j]];
                if(e.to>0) num[i][e.to-n]=e.flow;
            }
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
                printf("%d ",num[i][j]);
            puts("");
        }
    }
    return 0;
}
/*
4 4
1 2 6 3
3 5 3 1
1 2
2 3
3 4
4 2
*/


你可能感兴趣的:(ACM,codeforces,最大流)