UVA 753 A Plug for UNIX (最大流)

关键在建图,转换器连一条容量无限的边表示可以转化无数次,设备的插头连源点,插座连汇点。

dinic手敲已熟练,输出格式又被坑,总结一下,输出空行多case的,一个换行是必要的,最后一个不加空行,有Testcase最后一个不要换行,没有testcase最后一个要加换行,想起那天gold miner PE了两发。

对dinic网络流的简单理解:bfs找有没有增广路,dfs增广。

关键的概念:反向边,给一个反悔的机会。

#include<bits/stdc++.h>
using namespace std;
int n,m;
map<string,int> mp;
map<string,int>::iterator it;
#define MP make_pair
#define PB push_back
#define fi first
#define se second

int id_cnt;

int ID(const string &s)
{
    if((it=mp.find(s))!=mp.end()) return it->se;
    mp.insert(MP(s,id_cnt));
    return id_cnt++;
}

const int maxn = 404, INF = 0x3f3f3f3f;
int S,T;
struct Edge
{
    int v,nxt,cap,flow;
}edges[maxn<<1];

int head[maxn],cur[maxn],ecnt;

void addEdge(int u,int v,int c)
{
    edges[ecnt].nxt = head[u];
    edges[ecnt].cap = c;
    edges[ecnt].flow = 0;
    edges[ecnt].v = v;
    head[u] = ecnt++;
}

void AddEdge(int u,int v,int c)
{
    addEdge(u,v,c);
    addEdge(v,u,0);
}


int d[maxn];
bool vis[maxn];
bool bfs()
{
    memset(vis,0,sizeof(bool)*id_cnt);
    queue<int> q;
    q.push(S);
    d[S] = 0; vis[S] = true;
    while(q.size()){
        int u = q.front(); q.pop();
        for(int i = head[u]; ~i; i = edges[i].nxt){
            Edge &e = edges[i];
            if(!vis[e.v] && e.cap>e.flow){
                vis[e.v] = true;
                d[e.v] = d[u]+1;
                q.push(e.v);
            }
        }
    }
    return vis[T];
}

int dfs(int u,int a)
{
    if(u == T||!a) return a;
    int flow = 0,f;
    for(int &i = cur[u]; ~i; i = edges[i].nxt){
        Edge &e = edges[i];
        if(d[e.v] == d[u]+1 && (f = dfs(e.v,min(a,e.cap-e.flow))>0)){
            e.flow += f;
            edges[i^1].flow -= f;
            flow += f;
            a -= f;
            if(!a) break;
        }
    }
    return flow;
}

int MaxFlow()
{
    int ret = 0;
    while(bfs()){
        memcpy(cur,head,sizeof(int)*id_cnt);
        ret += dfs(S,INF);
    }
    return ret;
}

void init()
{
    memset(head,-1,sizeof(head));
    mp.clear(); id_cnt = 2;
    ecnt = 0;
}

int main()
{
    //freopen("in.txt","r",stdin);
    char str1[42],str2[42];
    int Testcase; scanf("%d",&Testcase);
    S = 0; T = 1;
    while(Testcase--){
        int n,m,k;
        init();
        scanf("%d",&n);
        for(int i = 0; i < n; i++){
            scanf("%s",str1);
            AddEdge(ID(str1),T,1);
        }
        scanf("%d",&m);
        for(int i = 0; i < m; i++){
            scanf("%s%s",str1,str2);
            AddEdge(S,ID(str2),1);
        }
        scanf("%d",&k);
        for(int i = 0; i < k; i++){
            scanf("%s%s",str1,str2);
            AddEdge(ID(str1),ID(str2),INF);
        }
        int ans = m-MaxFlow();
        printf("%d\n",ans);
        if(Testcase)putchar('\n');
    }
    return 0;
}

 

posted @ 2015-08-26 00:25  陈瑞宇  阅读(178)  评论(0编辑  收藏  举报