HDU - 3472 HS BDC (混合图欧拉路径)

题意:

将每个单词看为一个边,那么很明显就是一个混合图欧拉路径

分析:

首先,还是在网络流计算混合图欧拉回路的基础上进行,因为欧拉回路一定满足欧拉路径。

其次,如果有且仅有两个点入度出度差为奇数,那么给这两点加上边,判断是否存在欧拉回路。

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 210;
//最大流ISAP部分
const int MAXM = 20100;
const int INF = 0x3f3f3f3f;
struct Edge{
    int to,next,cap,flow;
}edge[MAXM];

int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

void init(){
    tol = 0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w,int rw = 0){
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].next = head[u];
    edge[tol].flow = 0;
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = rw;
    edge[tol].next = head[v];
    edge[tol].flow = 0;
    head[v] = tol++;
}

int sap(int start,int end,int N){
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u = start;
    pre[u] = -1;
    gap[0] = N;
    int ans = 0;
    while(dep[start] < N){
        if(u == end){
            int Min = INF;
            for(int i = pre[u]; i != -1;i = pre[edge[i^1].to])
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            for(int i = pre[u];i != -1;i = pre[edge[i^1].to]){
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
            }
            u = start;
            ans += Min;
            continue;
        }
        bool flag = false;
        int v;
        for(int i = cur[u];i != -1;i = edge[i].next){
            v = edge[i].to;
            if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]){
                flag = true;
                cur[u] = pre[v] = i;
                break;
            }
        }
        if(flag){
            u = v;
            continue;
        }
        int Min = N;
        for(int i = head[u];i != -1;i = edge[i].next)
            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
                Min = dep[edge[i].to];
                cur[u] = i;
            }
        gap[dep[u]]--;
        if(!gap[dep[u]])return ans;
        dep[u] = Min+1;
        gap[dep[u]]++;
        if(u != start)u = edge[pre[u]^1].to;
    }
    return ans;
}
//the end of 最大流部分

int in[MAXN],out[MAXN];//每个点的出度和入度

char s[100];

int fa[MAXN];

int find(int x){
    return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}

bool vis[MAXN];


int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
    int m;
    scanf("%d",&T);
    for(int cs=1;cs<=T;cs++){
        scanf("%d",&m);
        init();
        int u,v,w;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        for(int i=0;i<MAXN;i++){
            fa[i]=i;
        }
        memset(vis,0,sizeof vis);
        while(m--){
            scanf("%s%d",s,&w);
            u=s[0]-'a'+1;
            v=s[strlen(s)-1]-'a'+1;
            out[u]++; in[v]++;
            int fu=find(u);
            int fv=find(v);
            vis[u]=vis[v]=1;
            if(fu!=fv) {
                fa[fu]=fv;
            }
            if(w == 1)//双向
                addedge(u,v,1);
        }
        bool flag = true;
        int cnt=0;
        vector<int>vec;
        for(int i=1;i<=26;i++){
            if(vis[i]&&fa[i]==i) cnt++;
            if((out[i] - in[i])&1)
                vec.push_back(i);
        }
        printf("Case %d: ",cs);
        if(cnt!=1||(vec.size()!=2&&vec.size()!=0)){
            printf("Poor boy!\n");
            continue;
        }
        if(vec.size()==2){
            out[vec[0]]++;in[vec[1]]++;
            addedge(vec[0],vec[1],1);
        }
        for(int i = 1;i <= 26;i++){
            if((out[i]-in[i])&1==0&&out[i] - in[i] > 0)
                addedge(0,i,(out[i] - in[i])/2);
            else if((out[i]-in[i])&1==0&&in[i] - out[i] > 0)
                addedge(i,27,(in[i] - out[i])/2);
        }
        sap(0,27,28);
        for(int i = head[0]; i != -1;i = edge[i].next)
            if(edge[i].cap > 0 && edge[i].cap > edge[i].flow){
                flag = false;
                break;
            }
        if(flag)printf("Well done!\n");
        else printf("Poor boy!\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/88780558
BDC
Hs