POJ - 1087 A Plug for UNIX (網絡流)
阿新 • • 發佈:2018-08-01
inf turn his size get case ora clu 標記
原題鏈接
題意:
給定 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("!!!!!\n"); 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\n",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 }
POJ - 1087 A Plug for UNIX (網絡流)