zoukankan      html  css  js  c++  java
  • POJ

    原题链接

    题意:

    给定 N 个不同类型插座,每个插座只能插一个相对应的设备 ;

    现有 M 个人,给出每个人名字和设备的插头类型,然后给定 K 种转换器,每种转换器的数量都是无限的,每种转化器描述为: 插座类型,插头类型;

    现在问至少有多少个人的设备无法插入。

    思路:

    一个典型的最大流问题,设定超级源点 S , 超级汇点 T ,将每种插座与 S 相连,流量为1;将所有人的插头类型统计一下,并记录数量,然后将其与汇点相连,流量为每种插头的数量;

    记录所有的转换器,用 Floyd 算出 每种插头最终可以转化插头并将这个插头与对应的插座相连(如果都存在的话),最后跑一遍最大流,就是能够使用插座的人数,剩下的即为答案;

      1 /*
      2 * @Author: windystreet
      3 * @Date:   2018-07-31 20:57:04
      4 * @Last Modified by:   windystreet
      5 * @Last Modified time: 2018-08-01 11:57:21
      6 */
      7 
      8 #include <stdio.h>
      9 #include <algorithm>
     10 #include <string.h>
     11 #include <vector>
     12 #include <iostream>
     13 #include <map>
     14 #include <string>
     15 #include <queue>
     16 #include <utility>
     17 
     18 using namespace std;
     19 
     20 #define X first
     21 #define Y second
     22 #define eps  1e-2
     23 #define gcd __gcd
     24 #define pb push_back
     25 #define PI acos(-1.0)
     26 #define lowbit(x) (x)&(-x)
     27 #define bug printf("!!!!!
    ");
     28 #define mem(x,y) memset(x,y,sizeof(x))
     29 
     30 
     31 typedef long long LL;
     32 typedef long double LD;
     33 typedef pair<int,int> pii;
     34 typedef unsigned long long uLL;
     35 
     36 const int maxn = 1000+2;
     37 const int INF  = 1<<30;
     38 const int mod  = 1e9+7;
     39 
     40 struct Edge{
     41      int from,to,cap,flow;
     42 };
     43 
     44 struct Dinic
     45 {
     46     int n,m,s,t;
     47     vector<Edge>edge;
     48     vector<int>G[maxn];
     49     bool vis[maxn];
     50     int d[maxn];
     51     int cur[maxn];
     52     void init(int n){
     53         this->n = n;
     54         for(int i=0;i<=n;i++)G[i].clear(),edge.clear();
     55     }
     56     void addedge(int from,int to,int cap){
     57         edge.pb((Edge){from,to,cap,0});
     58         edge.pb((Edge){to,from,0,0});
     59         m = edge.size();
     60         G[from].pb(m-2);
     61         G[to].pb(m-1);
     62     }
     63     bool bfs(){
     64         mem(vis,0);
     65         queue<int>Q;
     66         Q.push(s);
     67         d[s] = 0;
     68         vis[s] = 1;
     69         while(!Q.empty()){
     70             int x = Q.front(); Q.pop();
     71             int sz = G[x].size();
     72             for(int i=0;i<sz;++i){
     73                 Edge &e = edge[G[x][i]];
     74                 if(!vis[e.to] && e.cap>e.flow){
     75                     vis[e.to] = 1 ;
     76                     d[e.to] = d[x] + 1;
     77                     Q.push(e.to); 
     78                 }
     79             }
     80         }
     81         return vis[t];
     82     }
     83     int dfs(int x,int a){
     84         if(x == t || a == 0)return a;
     85         int flow = 0,f;
     86         int sz = G[x].size();
     87         for(int &i = cur[x];i<sz;i++){
     88             Edge &e = edge[G[x][i]];
     89             if(d[x] + 1 == d[e.to] && (f = dfs(e.to,min(a,e.cap - e.flow)))>0){
     90                 e.flow += f;
     91                 edge[G[x][i]^1].flow -=f;
     92                 flow += f;
     93                 a -= f;
     94                 if(a==0)break;
     95             }
     96         }
     97         if(!flow) d[x] = -2;
     98         return flow;
     99     }
    100     int maxflow(int s,int t){
    101         this->s = s; this -> t = t;
    102         int flow = 0;
    103         while(bfs()){
    104             mem(cur,0);
    105             flow += dfs(s,INF);
    106         }
    107         return flow;
    108     }
    109 };
    110 int vis1[410];
    111 int vis2[420];
    112 int dp[400][400];
    113 int n,m,c,s = 0 ,t = 808;
    114 map<string,int>id;
    115 string s1,s2,name;
    116 Dinic dinic;
    117 void solve(){
    118     id.clear();
    119     int cnt = 1;
    120       mem(dp,0x3f3f3f3f);
    121     cin>>n;
    122     for(int i=1;i<=n;i++){
    123         cin>>s1;
    124         id[s1] = cnt;                     // 记录每一个插座的id
    125         dinic.addedge(s,cnt,1);
    126         vis1[cnt++] = 1;                // 标记该类型的插座已经存在
    127     }
    128     cin>>m;
    129     map<int,int>mp;
    130     mp.clear();
    131     for(int i=1;i<=m;i++){
    132         cin>>name>>s1;
    133         if(!id[s1]){
    134             id[s1]=cnt;
    135             cnt++;
    136         }
    137         mp[id[s1]]++;                    // 记录每种插头出现的次数
    138     }
    139     map<int,int>::iterator it = mp.begin();
    140     for(;it!=mp.end();it++){
    141         dinic.addedge(it->X+400,t,it->Y);// 插头与汇点相连,流量为插头数量
    142         vis2[it->X] = 1;                // 标记该类型的插头已经存在
    143     }
    144     cin>>c;
    145     for(int i=1;i<=c;i++){
    146         cin>>s1>>s2;
    147         if(!id[s1]) id[s1] = cnt++;
    148         if(!id[s2]) id[s2] = cnt++;
    149         dp[id[s1]][id[s2]] = 1;
    150     }
    151     for(int k = 1 ;k <= cnt;k++){        // floyd处理可转化的结果
    152         for(int i = 1;i <= cnt;i++ ){
    153             for(int j = 1;j<=cnt;j++){
    154                 if(dp[i][k]==1&&dp[k][j]==1){
    155                     dp[i][j] =  1;
    156                 }
    157             }
    158         }
    159     }         
    160     for(int i=1;i<=cnt;i++){
    161         if(vis1[i]&&vis2[i]){
    162             dinic.addedge(i,i+400,1);   // 如果该类型的插座和插头都存在,就相连
    163         }
    164     }
    165     for(int i=1;i<=cnt;i++){
    166         for(int j=1;j<=cnt;j++){
    167             if(dp[i][j]==1&&vis1[j]&&vis2[i]){
    168                 dinic.addedge(j,i+400,1); // 转化之后的结果
    169             }
    170         }
    171     }
    172     int ans = dinic.maxflow(s,t);
    173     printf("%d
    ",m-ans );
    174     return;
    175 }
    176 
    177 int main()
    178 {
    179 //    freopen("in.txt","r",stdin);
    180 //    freopen("out.txt","w",stdout);
    181     ios::sync_with_stdio(false);
    182     int t = 1;
    183     //scanf("%d",&t);
    184     while(t--){
    185     //    printf("Case %d: ",cas++);
    186         solve();
    187     }
    188     return 0;
    189 }
  • 相关阅读:
    Python 工匠:编写条件分支代码的技巧
    component-scan标签的use-default-filters属性的作用以及原理分析
    Serverless 架构的优点和缺点
    5 种使用 Python 代码轻松实现数据可视化的方法
    曾经我是一个只会excel的数据分析师,直到我遇到了……
    月薪45K的Python爬虫工程师告诉你爬虫应该怎么学,太详细了!
    用 Python 构建一个极小的区块链
    第六章 程序数据集散地;数据库
    MyBankgon功能
    第四章 深入C#的string类
  • 原文地址:https://www.cnblogs.com/windystreet/p/9402515.html
Copyright © 2011-2022 走看看