POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

题目:

POJ最近总是炸

所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157


题解:

题很长,但其实就是给个有源汇带下界网络流(+是源,-是汇),求最小流

求法:

1.模仿可行流建图,但是不加t到s的INF边

2.跑最大流

3.加t到sINF边

4.跑最大流

5.如果两次答案相加不等于sum,无解;

6.如果有解,t到s的反边流量就是答案

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define N 205
#define M 20005
#define INF 0x3f3f3f3f
using namespace std;
int n,m,s,t,S,T,c,cur[N],head[N],d[N],sum,ecnt=1,ans,lev[N];
char a[N],b[N];
queue<int> q;
struct adj
{
    int nxt,v,w;
}e[M];
int calc(char j[])
{
    if (j[0]=='+') return n+1;
    if (j[0]=='-') return n+2;
    int ans=0,s=strlen(j);
    for (int i=0;i<s;i++) ans*=10,ans+=j[i]-'0';
    return ans;
}
void add(int u,int v,int w)
{
    e[++ecnt].v=v;e[ecnt].w=w;e[ecnt].nxt=head[u];head[u]=ecnt;
    e[++ecnt].v=u;e[ecnt].w=0;e[ecnt].nxt=head[v];head[v]=ecnt;
}
void init()
{
    memset(head,0,sizeof(head));
    memset(d,0,sizeof(d));
    ecnt=1;ans=sum=0;
}
bool bfs()
{
    for (int i=1;i<=T;i++)
        cur[i]=head[i],lev[i]=-1;
    q.push(S);lev[S]=1;
    while (!q.empty())
    {
        int u=q.front();q.pop();
        for (int i=head[u],v;i;i=e[i].nxt)
            if (lev[v=e[i].v]==-1 && e[i].w>0)
                q.push(v),lev[v]=lev[u]+1;
    }
    return lev[T]!=-1;
}
int dfs(int u,int flow)
{
    if (u==T) return flow;
    int ret=0,v,delta;
    for (int &i=cur[u];i;i=e[i].nxt)
        if (lev[v=e[i].v]==lev[u]+1 && e[i].w>0)
        {
            delta=dfs(v,min(flow-ret,e[i].w));
            if (delta)
            {
                e[i].w-=delta;e[i^1].w+=delta;ret+=delta;
                if (ret==flow) break;
            }
        }
    return ret;
}
int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
    if (n==0 && m==0) break;
    init();
    s=n+1;t=s+1;S=t+1;T=S+1;
    for (int i=1,u,v;i<=m;i++)
    {
        scanf("%s%s%d",a,b,&c);
        u=calc(a);v=calc(b);
        add(u,v,INF-c);
        d[u]-=c;d[v]+=c;
    }
    for (int i=1;i<=n+2;i++)
        if (d[i]>0) add(S,i,d[i]),sum+=d[i];
        else if (d[i]<0) add(i,T,-d[i]);
    while (bfs()) ans+=dfs(S,INF);
    add(t,s,INF);
    while (bfs()) ans+=dfs(S,INF);
    if (ans!=sum) puts("impossible");
    else printf("%d
",e[ecnt].w);
    }
    return 0;
}