zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3083016.html
Copyright © 2011-2022 走看看