Wormhole is a kind of two-way tunnel between two planets which can make it possible to transport large amounts of resources without time. Of course, building Wormhole has lots of requirements, only some pairs of the planet can build Wormhole and it costs lots of money. Country G is a very big country which has a lot of planets. There are several resource planets in country G. One resource planet can provide for a factory, and a factory need a resource planet to provide resource. Due to various reasons, country G has build some factories in several planets without considering about resource planets. So it depends on Wormhole to transport resource if a factory can't get resource from local. It is your task to make a plan to build Wormholes which can make most factories run and use the least money in this case.
Input
The input consist of multiple cases. For each test case, the first line contains an integer N (0 < N ≤ 200) which indicates the number of planets in country G. Then followed by Nlines, each line contains two integers Pi, Si .Pi is the number of factories in planet i, if Si =1, planet i is a resource planet; if Si =0, planet i isn't a resource planet. At most of 4 planets have factories and at most of 4 planets are resource planets. The next line contains an integer M (0 < M ≤ 5000) which indicates the number of pairs of planet which can build Wormhole. Then followed by M lines, each line contains three integers xi, yi, ci, which indicate building Wormhole between planet xi and planet yi costs ci.
Output
The output contains one line per case. It contains the maximum of factories that can get resource and the the minimum of money when the maximum of factories that can get resource.
Sample Input
2 1 0 0 1 1 1 2 3
Sample Output
1 3
思路:我是渣渣,初学者,讲不好,就不误导大家了,仅仅贴出代码供自己借鉴。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define MAX 5010
#define MIN 1010
#define INF 1e9
queue<int> qu;
struct planet
{ int a,b;
}arr[MIN];
struct node
{ int v,len;
node *next;
}*head[MAX*2],tree[MAX*2];
bool in[MIN][MIN];
int cost[MIN][MIN],n,nn,k,tot,m,dp[MIN],st[MIN],fac[MIN],res[MIN],orik,ptr,ans,ansi,num;
void init()
{ int i,j,t;
ptr=0;
orik=k;
memset(st,0,sizeof(st));
memset(in,0,sizeof(in));
memset(head,NULL,sizeof(head));
for(i=0;i<tot;i++)
res[k++]=fac[i];
nn=1<<k;
for(j=0;j<n;j++)
for(i=0;i<nn;i++)
cost[j][i]=INF;
for(i=0;i<k;i++)
{ st[res[i]]=1<<i;
cost[res[i]][st[res[i]]]=0;
}
}
void AddEdge(int a,int b,int c)
{ tree[ptr].v=b;
tree[ptr].len=c;
tree[ptr].next=head[a];
head[a]=&tree[ptr++];
}
void Spfa()
{ int i,j,v,nst,len;
while(!qu.empty())
{ j=qu.front()/MAX;
i=qu.front()%MAX;
qu.pop();
in[j][i]=false;
node *p=head[j];
while(p!=NULL)
{ v=p->v;
len=p->len;
nst=i|st[v];
if(cost[j][i]+len<cost[v][nst])
{ cost[v][nst]=cost[j][i]+len;
if(nst==i && !in[v][nst])
{ qu.push(v*MAX+nst);
in[v][nst]=true;
}
}
p=p->next;
}
}
}
void Steiner_Tree()
{ int i,j,t,s;
for(i=0;i<nn;i++)
{ for(j=0;j<n;j++)
{ if(st[j] && !(st[j]&i))
continue;
for(t=(i-1)&i;t;t=(t-1)&i)
cost[j][i]=min(cost[j][i],cost[j][t|st[j]]+cost[j][(i-t)|st[j]]);
if(cost[j][i]<INF)
{ qu.push(j*MAX+i);
in[j][i]=true;
}
}
Spfa();
}
}
bool Check(int s)
{ int i,cnt=0;
for(i=0;i<orik;i++)
if(s&(1<<i))
cnt++;
for(i=orik;i<k;i++)
if(s&(1<<i))
cnt-=arr[fac[i-orik]].a;
return cnt<=0;
}
void Solve_DP()
{ int i,j,t;
for(i=0;i<nn;i++)
{ dp[i]=INF;
for(j=0;j<n;j++)
dp[i]=min(dp[i],cost[j][i]);
}
for(i=0;i<nn;i++)
if(Check(i))
for(t=(i-1)&i;t;t=(t-1)&i)
if(Check(t) && Check(i-t))
dp[i]=min(dp[i],dp[t]+dp[i-t]);
for(i=0;i<nn;i++)
if(dp[i]<INF && Check(i))
{ int cnt=0;
for(j=0;j<orik;j++)
if(i&(1<<j))
cnt++;
if(cnt>ans)
{ ans=cnt;
ansi=dp[i];
}
else if(cnt==ans)
ansi=min(ansi,dp[i]);
}
}
int main()
{ int t,i,j,a,b,c;
while(~scanf("%d",&n))
{ ans=ansi=0;
num=k=tot=0;
for(i=0;i<n;i++)
{ scanf("%d%d",&arr[i].a,&arr[i].b);
if(arr[i].a && arr[i].b)
{ num++;
arr[i].a--;
arr[i].b--;
}
if(arr[i].a)
fac[tot++]=i;
if(arr[i].b)
res[k++]=i;
}
init();
scanf("%d",&m);
while(m--)
{ scanf("%d%d%d",&a,&b,&c);
a--;b--;
AddEdge(a,b,c);
AddEdge(b,a,c);
}
Steiner_Tree();
Solve_DP();
printf("%d %d\n",ans+num,ansi);
}
}