题目:http://acm.pku.edu.cn/JudgeOnline/problem?id=1087
终于做到一个最大流的题目了,虽然我的图论是很水的(其实什么都比较水)。这个题目读懂之后,假设每个电器消耗的电能都是单位电能。这样就问题就转化成求插座组成的网络最大可以消耗掉的电能了。假设原始插座都连接至一个能量提供点,电器都连结至一个能量消耗点。这样就转化成简单的求网络最大流的问题。
至于求最大流的过程,原先不是太懂。现在再学习一下。
cap[N][N],flow[N][N]。分别标记未被消耗的和已经消耗的。
1,2点分别标记起始点和终止点。
求图中一条通路,用dps的方法。从1点出发,找到一条到达2点的路即返回。
然后重新对cap,flow进行标记。直到没有通路被找到
#include <iostream>
#include <vector>
#define inf 100000
using namespace std;
int cap[420][420],flow[420][420];
int n_rec,n_item,n_adp;
char capp[420][30];
int path_find_index[1000];
vector<int> found_path;
int v_count,capp_count;
char ss[30];
int id_count=2;
int _find_path(int f)
{
if(path_find_index[f]!=0) return 0;
path_find_index[f]=1;
int i;
for (i=1;i<=v_count;i++)
{
if(cap[f][i]-flow[f][i]>0)
{
if(i==2)
{
found_path.push_back(2);
found_path.push_back(f);
return 1;
}
if(_find_path(i))
{
found_path.push_back(f);
return 1;
}
}
}
path_find_index[f]=2;
return 0;
}
int remain(int idf,int idt)
{
return cap[idf][idt]-flow[idf][idt];
}
int find_path()
{
for(int i=1;i<=v_count;i++) path_find_index[i]=0;
found_path.clear();
return _find_path(1);
}
int IsIn()
{
for (int i=3;i<=id_count;i++)
{
if(!strcmp(capp[i],ss))
return i;
}
return -1;
}
void plug()
{
//capp_count=2;
cin>>n_rec;
int i,j;
for(i=1;i<=310;i++)
for(j=1;j<=310;j++)
{
cap[i][j]=flow[i][j]=0;
}
for (i=1;i<=n_rec;i++)
{
scanf("%s",ss);
int cur=IsIn();
if(cur==-1)
{
strcpy(capp[++id_count],ss);
++cap[1][id_count];
}
else
++cap[1][cur];
}
cin>>n_item;
for (i=1;i<=n_item;i++)
{
scanf("%s",ss);
scanf("%s",ss);
int cur=IsIn();
if (cur==-1)
{
strcpy(capp[++id_count],ss);
++cap[id_count][2];
}
else
++cap[cur][2];
}
cin>>n_adp;
for (i=1;i<=n_adp;i++)
{
int idr,idf;
scanf("%s",ss);
int cur=IsIn();
if (cur==-1)
{
strcpy(capp[++id_count],ss);
idf=id_count;
}
else
idf=cur;
scanf("%s",ss);
cur=IsIn();
if (cur==-1)
{
strcpy(capp[++id_count],ss);
idr=id_count;
}
else
idr=cur;
cap[idr][idf]=inf;
}
v_count=id_count;
while (find_path())
{
int len=found_path.end()-found_path.begin();
int i,tt;
int cr=remain(found_path[len-1],found_path[len-2]);
for (i=len-2;i>=1;i--)
{
tt=remain(found_path[i],found_path[i-1]);
if(tt<cr) cr=tt;
}
for (i=len-1;i>=1;i--)
{
int idf,idt;
idf=found_path[i];
idt=found_path[i-1];
flow[idf][idt]+=cr;
flow[idt][idf]-=cr;
}
}
int res=0;
for (int i=3;i<=v_count;i++) res+=flow[1][i];
printf("%d"n",n_item-res);
}
int main()
{
freopen("test.txt","r",stdin);
plug();
return 0;
}
另外就是读取的过程,要判断读进来的插座,是否已经存在。