很好的题。。
很推荐。。感谢博文http://endlesscount.blog.163.com/blog/static/821197872012525113427573/
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <queue>
#include <iostream>
#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define repn(i,j,k) for(int i = j; i <= k;i++)
using namespace std;
const int N = 250;
int S[N],P[N];
int rs,fx[N];
int fac[N],in[N][1<<10];
int dp[N][1<<10],d[1<<10];
int n,m;
queue<pii > Q;
vector<pii >G[N];
void up(int &x,int y){
if(x == -1) x = y;
else x = min(x,y);
}
void spfa(){
while(!Q.empty()){
int u = Q.front().first , sta = Q.front().second; Q.pop();
for(int i = 0;i < G[u].size();i++){
int v = G[u][i].first, w =G[u][i].second;
if(dp[v][sta|fx[v]]==-1 || dp[v][sta|fx[v]] > dp[u][sta]+w){
dp[v][sta|fx[v]] = dp[u][sta] + w;
if(!in[v][sta|fx[v]] && sta == (sta|fx[v])){
in[v][sta|fx[v]] = 0;
Q.push(mp(v,sta|fx[v]));
}
}
}
in[u][sta] = 0;
}
}
bool check(int sta){
int ret = 0;
for(int i = 0;i<rs;i++)
if(sta & (1<<i))
ret += fac[i];
return ret>=0;
}
int ccnt(int sta){
int ret = 0;
for(int i = 0;i < rs;i++)
if(sta & (1<<i) && fac[i] < 0)
ret++;
return ret;
}
int main(){
int t;
int u,v,w;
while(scanf("%d",&n)!=EOF){
rs = 0;
memset(dp,-1,sizeof(dp));
memset(d,-1,sizeof(d));
memset(fx,0,sizeof(fx));
memset(in,0,sizeof(in));
int gg = 0;
repn(i,1,n){
scanf("%d %d",P+i,S+i);
if(P[i] && S[i]) P[i]--,S[i]--,gg++;
if(P[i] || S[i]){
fac[rs] = P[i] - S[i];
fx[i] = 1<<rs;
dp[i][1<<rs] = 0;
rs++;
}
}
repn(i,0,n)
G[i].clear();
scanf("%d",&m);
repn(i,1,m){
scanf("%d %d %d",&u,&v,&w);
G[u].push_back(mp(v,w));
G[v].push_back(mp(u,w));
}
int maxSta = (1 << rs)-1;
while(!Q.empty()) Q.pop();
repn(sta,0,maxSta){
repn(j,1,n){
if(fx[j] && !(fx[j]&sta)) continue;
for(int i = (sta-1)&sta; i; i=(i-1)&sta){
if(dp[j][i|fx[j]]!=-1 && dp[j][(sta-i)|fx[j]]!=-1){
up(dp[j][sta] , dp[j][i|fx[j]]+dp[j][(sta-i)|fx[j]]);
}
}
if(dp[j][sta]!=-1){
// printf("fuck \n");
Q.push(mp(j,sta)),in[j][sta] = 1;
}
}
spfa();
}
repn(i,0,maxSta){
repn(j,1,n){
if(dp[j][i]!=-1)
up(d[i],dp[j][i]);
}
// printf("d[%d]=%d\n",i,d[i]);
}
//森林
int tmp;
int bef = 0, ans = 0;
repn(sta,0,maxSta){
if(check(sta)){
for(int j = sta&(sta-1); j ; j = (j-1)&sta){
if(check(j) && check(sta-j) && d[j]!=-1 && d[sta-j]!=-1)
up(d[sta],d[j]+d[sta-j]);
}
if(d[sta]!=-1 && ((tmp = ccnt(sta)) > bef || (tmp == bef && d[sta] < ans))){
bef = tmp , ans = d[sta];
}
}
}
printf("%d %d\n",bef+gg,ans);
}
return 0;
}