poj1087 A Plug for UNIX(网络流最大流)

时间:2022-09-05 11:09:45

http://poj.org/problem?id=1087

好久没遇见过这么坑的题了这个题真是挫的够可以的。题目大意:你作为某高管去住宿了,然后宾馆里有几种插座,分别有其对应型号,你携带了几种用电器(手机,电脑一类的),

也有其对应型号;可是不一定用电器就能和插座匹配上,于是宾馆的商店里提供了一些转换器,这些转换器可以将某一型号电源转换成另一型号的。问,你的用电器最少会有多少种无

法充电。也就是问可以用上电的用电器的最大数目,之后用电器总数减去此可用电最大数目即可得到最小不能用电数目。

一开始以为直接将插座,转换器,用电器匹配后跑个最大流模板就行,后来发现想的太简单了。

分析:

1:用电器可直接连插座;

2:用电器可以连接转换器再连接上插座;

3:转换器之间可以相互连接;

4:转换器转换作用是双向的,比如给定转换器可对A和B进行转换,则此转换器可以将A转换成B,也可以将B转换成A;

5:每种转换器的数目是无限的;

6:一个插座只能连接产生一个出处。

7:虚拟一个源点一个汇点即可,源点到插座和插头到汇点的流量为1。

按照这些建图失误了四次之后终于成功A过了。

附加详细建图步骤的备注的AC代码和一组测试数据(测试答案应当为0)

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
#define oo 0x3f3f3f3f
int G[][], n, m, p, vis[];
char receptacle[][];
char plug[][];
struct ad
{
char in[], out[];
}adapter[]; bool bfs(int Start, int End)
{
memset(vis, , sizeof(vis));
vis[Start] = ; queue<int>Q;
Q.push(Start); while(Q.size())
{
int now = Q.front();
Q.pop(); if(now == End)
return true; for(int i=; i<=End; i++)
{
if(!vis[i] && G[now][i]>)
{
vis[i] = vis[now] + ;
Q.push(i);
}
}
} return false;
} int dfs(int Start, int End, int Maxflow)
{
if(Start == End)
return Maxflow; int nowflow = ; for(int i=; i<=End; i++)
{
if(vis[i] == vis[Start] + && G[Start][i]>)
{
int flow = min(G[Start][i], Maxflow - nowflow); flow = dfs(i, End, flow); G[Start][i] -= flow;
G[i][Start] += flow; nowflow += flow; if(nowflow == Maxflow)
break;
}
} return nowflow;
}
int dinic(int Start, int End)
{
int ans = , s; while(bfs(Start, End))
{
s = dfs(Start, End, oo);
if(!s)break;
ans += s;
} return ans;
}
int main()
{
while(~scanf("%d", &n))
{
memset(G, , sizeof(G)); for(int i=; i<=n; i++)
scanf("%s", receptacle[i]); scanf("%d", &m);
for(int i=; i<=m; i++)
{
scanf("%*s %s", plug[i]);
for(int j=; j<=n; j++)
{
if(strcmp(receptacle[j], plug[i]) == )///插头和插座可直接连
{
G[j][n+p+i] = ;
}
}
} scanf("%d", &p);
for(int i=; i<=p; i++)
scanf("%s %s", adapter[i].in, adapter[i].out); for(int i=; i<=p; i++)///1~n是插座,n+1~n+p是转换器,n+p+1~n+p+m是插头
{
for(int j=; j<=n; j++)
{
if(strcmp(receptacle[j], adapter[i].in)== || strcmp(receptacle[j], adapter[i].out)==)///插座和转换器匹配
{
G[j][n+i] = ;
}
} for(int j=; j<=m; j++)
{
if(strcmp(plug[j], adapter[i].out)== || strcmp(plug[j], adapter[i].in)==)///转换器和插头匹配
{
G[n+i][n+p+j] = ;
}
}
} for(int i=; i<=p; i++)///转换器之间相连
{
for(int j=; j<=p; j++)
{
if(i!=j && strcmp(adapter[i].in, adapter[j].out)==)
G[n+i][n+j] = oo;
}
for(int j=; j<=p; j++)
{
if(i!=j && strcmp(adapter[i].out, adapter[j].in)==)
G[n+i][n+j] = oo;
}
} int Start = n+p+m+, End = Start+; for(int i=; i<=n; i++)///源点和插座相连
{
G[Start][i] = ;
} for(int i=; i<=m; i++)///插头和汇点相连
{
G[n+p+i][End] = ;
} printf("%d\n", m - dinic(Start, End));
}
return ;
} /*
16
A
D
X
A
D
A
D
X
D
A
D
D
X
D
X
D
14
CLOCK B
CLOCK B
CLOCK B
LAPTOP B
LAPTOP B
LAPTOP B
LAPTOP B
LAPTOP B
LAPTOP B
PAGER B
PAGER B
COMB X
CELL C
CELL C
4
C D
X D
B X
B A
*/