hdu3472HS BDC

来源:互联网 发布:航天科工33所 知乎 编辑:程序博客网 时间:2024/05/17 01:55

HS BDC

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1007    Accepted Submission(s): 411



Problem Description
IELTS is around the corner! love8909 has registered for the exam, but he still hasn’t got prepared. Now he decides to take actions. But when he takes out the New Oriental IELTS Vocabulary, he finds there are so many words. But love8909 doesn’t get scared, because he has got a special skill. If he can make a list with some meaningful words, he will quickly remember these words and will not forget them. If the last letter of some word Wa is the same as the first letter of some word Wb, then you can connect these two words and make a list of two words. If you can connect a word to a list, you will make a longer list.

While love8909 is making the list, he finds that some words are still meaningful words if you reverse them. For example, if you reverse the word “pat”, you will get another meaningful word “tap”.

After scanning the vocabulary, love8909 has found there are N words, some of them are meaningful if reversed, while others are not. Now he wonders whether he can remember all these words using his special skill.

The N-word list must contain every word once and only once.
 

Input
An integer T (T <= 50) comes on the first line, indicating the number of test cases.

On the first line of each test cases is an integer N (N <= 1000), telling you that there are N words that love8909 wants to remember. Then comes N lines. Each of the following N lines has this format: word type. Word will be a string with only ‘a’~’z’, and type will be 0(not meaningful when reversed) or 1(meaningful when reversed). The length of each word is guaranteed to be less than 20.

 

Output
The format of the output is like “Case t: s”, t is the number of the test cases, starting from 1, and s is a string.
For each test case, if love8909 can remember all the words, s will be “Well done!”, otherwise it’s “Poor boy!”

 

Sample Input
36aloha 0arachnid 0dog 0gopher 0tar 1tiger 03thee 1earn 0nothing 02pat 1acm 0
 

Sample Output
Case 1: Well done!Case 2: Well done!Case 3: Poor boy!
Hint
In the first case, the word “tar” is still meaningful when reversed, and love8909 can make a list as “aloha-arachnid-dog-gopher-rat-tiger”. In the second case, the word “thee” is still meaningful when reversed, and love8909 can make a list as “thee-earn-nothing”. In the third case, no lists can be created.
 

Author
allenlowesy


解:这题是混合路的欧拉路径问题。

    1.首先判断图的连通性,若不连通,无解。

      2设立源点s和汇点t,若某点i入度<出度,连边(s,i,-deg[i]/2),若入度>出度,连边(i,t,deg[i]/2);对于任意定向的无向边(i,j,1)。

    3.若有两个度数为奇数的点,假设存在欧拉路径,添加一条容量为1的边,构成欧拉回路,不影响结果。若全为偶数,直接最大流。找到出入度为奇数的两个点,一个起点,out[起点]++,一个终点,in[终点]++,从起点向起点连容量为1边的即可。

    4若从S发出的边全部满流,证明存在欧拉回路(路径),否则不存在。

    ps:若要求输出路径,将网络中有()流量的边反向,加上原图的有向边,用套圈算法即可。

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <ctime>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define inf -0x3f3f3f3f#define lson k<<1, L, mid#define rson k<<1|1, mid+1, R#define mem0(a) memset(a,0,sizeof(a))#define mem1(a) memset(a,-1,sizeof(a))#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;const int maxn=1000 + 10;int in[maxn],out[maxn];int f[30];struct Edge{    int from,to,cap,flow;    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}};struct Dinic{    int n,m,s,t;                        //结点数,边数(包括反相弧),源点编号和汇点编号    vector<Edge>edges;                    //边表,edges[e]和edges[e^1]互为反相弧    vector<int>G[maxn];                    //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号    bool vis[maxn];                        //BFS使用    int d[maxn];                        //从起点到i的距离    int cur[maxn];                        //当前弧下标    void AddEdge(int from,int to,int cap){        edges.push_back(Edge(from,to,cap,0));        edges.push_back(Edge(to,from,0,0));        m=edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    void init(int n){        this->n=n;        for(int i=0;i<n;i++)            G[i].clear();        edges.clear();    }    bool BFS(){        mem0(vis);        queue<int>Q;        Q.push(s);        d[s]=0;        vis[s]=1;        while(!Q.empty()){            int x=Q.front();            Q.pop();            for(int i=0;i<G[x].size();i++){                    //只考虑残量网络中的弧                Edge& e=edges[G[x][i]];                if(!vis[e.to]&&e.cap>e.flow){                    vis[e.to]=1;                    d[e.to]=d[x]+1;                    Q.push(e.to);                }            }        }        return vis[t];    }    int DFS(int x,int a){        if(x==t||a==0)            return a;        int flow=0,f;        for(int& i=cur[x];i<G[x].size();i++){            Edge& e=edges[G[x][i]];            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){                e.flow+=f;                edges[G[x][i]^1].flow-=f;                flow+=f;                a-=f;                if(a==0)                    break;            }        }        return flow;    }    void Maxflow(int s,int t){        this->s=s;        this->t=t;        int flow=0;        while(BFS()){            mem0(cur);            flow+=DFS(s,INF);        }        bool flag=true;        for(int i=0;i<G[0].size();i++){            Edge& e=edges[G[0][i]];            if(e.cap>e.flow){                flag=false;                break;            }        }        if(!flag)            printf("Poor boy!\n");        else            printf("Well done!\n");    }};int find(int x){    return x == f[x] ? x : find(f[x]);}Dinic solve;char s[100];int main(){    int u,v,w;    int n,m,_;    scanf("%d",&_);    for(int case1=1;case1<=_;case1++){        scanf("%d",&n);        solve.init(n+3);    //这里注意要稍微大一点        for(int i=1;i<=26;i++)            f[i]=i;        mem0(out);        mem0(in);        for(int i=0;i<n;i++){            scanf("%s%d",s,&w);            u=s[0]-'a'+1,v=s[strlen(s)-1]-'a'+1;            out[u]++;            in[v]++;            int x=find(u);            int y=find(v);            if(x!=y){                f[x]=y;            }            if(w==1){                solve.AddEdge(u,v,1);            }        }        int num=0;        for(int i=1;i<=26;i++)      //是否连通            if(out[i]+in[i]!=0){                if(f[i]==i)                    num++;            }        if(num!=1){            printf("Case %d: Poor boy!\n",case1);            continue;        }        int cnt=0,start,end1;        for(int i=1;i<=26;i++){            if(out[i]+in[i]==0)                continue;            if((out[i]-in[i])&1){                if(cnt==0){                    start=i;                    out[i]++;                }                else{                    end1=i;                    in[i]++;                    solve.AddEdge(start,end1,1);                }                cnt++;            }            if(out[i]-in[i]>0)                solve.AddEdge(0,i,(out[i]-in[i])/2);            if(in[i]-out[i]>0)                solve.AddEdge(i,n+1,(in[i]-out[i])/2);        }        if(cnt!=2&&cnt!=0){            printf("Case %d: Poor boy!\n",case1);            continue;        }        printf("Case %d: ",case1);        solve.Maxflow(0,n+1);    }    return 0;}


 
0 0
原创粉丝点击