Word maker! 最大流dinic

link:http://acm.upc.edu.cn/problem.php?id=2161

这题的大题题意是给你N个多面体,每个多面体的每个面都有字母,然后告诉你几个单词,问你能拼出几个单词。

从这道题意不难看出这每个多面体只能每次提供一个字母,也就是说每个多面体预期所带的字母之间所能提供的流量为1 ,不难看出是个二分图,当时用的DFS果断超时,然后想到二分匹配时觉得二分匹配不熟,写了个EK最大流也超市。。。后来回到宿舍敲了一个DINIC果断88ms啊!刚才写了个二分匹配还是超市,不过QC他们的二分过了不知道为什么。。。

#include <stdio.h>
#include <iostream>
#include <queue>
#include <string.h>
#include <vector>
#define maxn 1050
using namespace std;
int m,n;
struct edge
{
    int u,v,cap,flow;
};
vector<edge>edges;
vector<edge>ed;
vector<int>g[maxn],G[maxn];
 
void addedge(int u,int v,int cap,int flow)
{
    edges.push_back((edge){u,v,cap,flow});
    edges.push_back((edge){v,u,0,0});
    int m;
    m = edges.size();
    g[u].push_back(m-2);
    g[v].push_back(m-1);
}
 
void init(int n)
{
    int i;
    for(i = 0;i <= n;i++)
    {
        g[i].clear();
    }
    edges.clear();
}
int vis[maxn],dis[maxn],cur[maxn];
int bfs(int s,int t,int n)
{
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(s);
    dis[s] = 0;
    vis[s] = 1;
 
    while(!q.empty())
    {
        int u,v;
        u = q.front();
        q.pop();
        for(int i = 0;i < g[u].size();i++)
        {
            edge &e = edges[g[u][i]];
            v = e.v;
            if(!vis[v] && e.cap-e.flow > 0)
            {
                vis[v] = 1;
                dis[v] = dis[u] +1;
                q.push(v);
            }
        }
    }
    return vis[t];
}
int dfs(int u,int a,int t)
{
    if(u == t || a == 0)
    return a;
    int v;
    int flow = 0,f;
    for(int& i = cur[u]; i < g[u].size();i++)
    {
        edge &e = edges[g[u][i]];
        v = e.v;
        if(dis[u]+1 == dis[v] &&(f = dfs(v,min(a,e.cap-e.flow),t)))
        {
            e.flow += f;
            edges[g[u][i]^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0)
            break;
        }
    }
 
    return flow;
}
int maxflow(int s,int t)
{
    int flow = 0;
    while(bfs(s,t,t))
    {
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,1000050,t);
    }
    return flow;
}
 
 
int main()
{
    int i,j;
    int t;
     
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d %d",&m,&n);
            init(100+m);
            int u,v;
            int word[30];
            for(u = 1;u <= m;u++)
            {
                addedge(0,u,1,0);
                char str[5005];
                scanf("%s",str);
                memset(word,0,sizeof(word));
                for(i = 0;str[i] != '\0';i++)
                {
                    if(str[i] >= 'a' && str[i] <= 'z')
                    str[i]-=32;
                    v = str[i]-'A';
 
                    if(!word[v])
                    addedge(u,m+v+1,1,0);
                    word[v] = 1;
 
                }
            }
            int ans = 0;
            ed = edges;
            for(i = 0;i <= m+28;i++)
            G[i] = g[i];
            for(u = 1;u <= n;u++)
            {
 
                edges = ed;
                memset(word,0,sizeof(word));
                for(i = 0;i <= m+28;i++)
                g[i] = G[i];
                char str[5005];
                scanf("%s",str);
                int len,res;
                len = strlen(str);
 
                for(i = 0;i < len;i++)
                {
                    if(str[i] >= 'a' && str[i]<='z')
                    str[i] -= 32;
                    v  = str[i]-'A';
                    word[v]++;
 
                }
                for(i = 0;i <= 25;i++)
                {
                    if(word[i])
                    addedge(m+i+1,m+27,word[i],0);
                }
 
                res = maxflow(0,m+26+1);
 
                if(res >= len)
                ans++;//,cout<<"yes"<<endl;
            }
            printf("%d\n",ans);
 
        }
    }
 
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/0803yijia/p/3083016.html