Problem Description
Tom is a commander, his task is destroying his enemy’s transportation system.

Let’s represent his enemy’s transportation system as a simple directed graph G with n nodes and m edges. Each node is a city and each directed edge is a directed road. Each edge from node u to node v is associated with two values D and B, D is the cost to destroy/remove such edge, B is the cost to build an undirected edge between u and v.

His enemy can deliver supplies from city u to city v if and only if there is a directed path from u to v. At first they can deliver supplies from any city to any other cities. So the graph is a strongly-connected graph.

He will choose a non-empty proper subset of cities, let’s denote this set as S. Let’s denote the complement set of S as T. He will command his soldiers to destroy all the edges (u, v) that u belongs to set S and v belongs to set T.

To destroy an edge, he must pay the related cost D. The total cost he will pay is X. You can use this formula to calculate X:

After that, all the edges from S to T are destroyed. In order to deliver huge number of supplies from S to T, his enemy will change all the remained directed edges (u, v) that u belongs to set T and v belongs to set S into undirected edges. (Surely, those edges exist because the original graph is strongly-connected)

To change an edge, they must remove the original directed edge at first, whose cost is D, then they have to build a new undirected edge, whose cost is B. The total cost they will pay is Y. You can use this formula to calculate Y:

At last, if Y>=X, Tom will achieve his goal. But Tom is so lazy that he is unwilling to take a cup of time to choose a set S to make Y>=X, he hope to choose set S randomly! So he asks you if there is a set S, such that Y<X. If such set exists, he will feel unhappy, because he must choose set S carefully, otherwise he will become very happy.
 

Input
There are multiply test cases.

The first line contains an integer T(T<=200), indicates the number of cases.

For each test case, the first line has two numbers n and m.

Next m lines describe each edge. Each line has four numbers u, v, D, B.
(2=<n<=200, 2=<m<=5000, 1=<u, v<=n, 0=<D, B<=100000)

The meaning of all characters are described above. It is guaranteed that the input graph is strongly-connected.
 

Output
For each case, output "Case #X: " first, X is the case number starting from 1.If such set doesn’t exist, print “happy”, else print “unhappy”.
 

Sample Input
2 3 3 1 2 2 2 2 3 2 2 3 1 2 2 3 3 1 2 10 2 2 3 2 2 3 1 2 2
 

Sample Output
Case #1: happy Case #2: unhappy
Hint
In first sample, for any set S, X=2, Y=4. In second sample. S= {1}, T= {2, 3}, X=10, Y=4.
 

Author
UESTC
 

Source




感觉官方题解说的好明白==

说一下对于有上下限制的网络流的更深一些点的理解:

网络流总结篇 的第16题的图是这个意思,但是建边的原理没说明白


给定的是A->B的范围是[c,d],对于点B而言,他的流量必须有C,人为补充的是d-c的可行流,对于点A来说,流出的流量至少是C,d-c的部分是可行流。

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int mm=1000000;
    const int mn=505*505*3;
    const int oo=1000000000;
    int node,src,dest,edge;
    int reach[mm],flow[mm],nxt[mm];
    int head[mn],work[mn],dis[mn],q[mn];
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    inline void prepare(int _node,int _src,int _dest)
    {
        node=_node,src=_src,dest=_dest;
        for(int i=0;i<node;++i)head[i]=-1;
        edge=0;
    }
    inline void addedge(int u,int v,int c1,int c2=0)
    {
        reach[edge]=v,flow[edge]=c1,nxt[edge]=head[u],head[u]=edge++;
        reach[edge]=u,flow[edge]=c2,nxt[edge]=head[v],head[v]=edge++;
    }
    bool Dinic_bfs()
    {
        int i,u,v,l,r=0;
        for(i=0;i<node;++i)dis[i]=-1;
        dis[q[r++]=src]=0;
        for(l=0;l<r;++l)
            for(i=head[u=q[l]];i>=0;i=nxt[i])
                if(flow[i]&&dis[v=reach[i]]<0)
                {
                    dis[q[r++]=v]=dis[u]+1;
                    if(v==dest)return 1;
                }
        return 0;
    }
    int Dinic_dfs(int u,int exp)
    {
        if(u==dest)return exp;
        for(int &i=work[u],v,tmp;i>=0;i=nxt[i])
            if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
            {
                flow[i]-=tmp;
                flow[i^1]+=tmp;
                return tmp;
            }dis[u]--;
        return 0;
    }
    int Dinic_flow()
    {
        int i,ret=0,delta;
        while(Dinic_bfs())
        {
            for(i=0;i<node;++i)work[i]=head[i];
            while(delta=Dinic_dfs(src,oo))ret+=delta;
        }
        return ret;
    }
    int Edge[40000],Flow[40000];
    int main()
    {
       // freopen("cin.txt","r",stdin);
        int n,m,t,cas=1;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            prepare(n+2,0,n+1);
            int sum=0;
            for(int i=0;i<m;i++)
            {
                int a,b,c,d;
                scanf("%d%d%d%d",&a,&b,&c,&d);
                d+=c;
                sum+=c;
                addedge(src,b,c);
                addedge(a,dest,c);
                Edge[i]=edge;
                Flow[i]=c;
                addedge(a,b,d-c);
            }
            printf("Case #%d: ",cas++);
            if(sum!=Dinic_flow())
            {
                puts("unhappy");
            }
            else
            {
                puts("happy");
            }
        }
        return 0;
    }