uva10269

来源:互联网 发布:医学英文单词软件 编辑:程序博客网 时间:2024/06/05 20:19

题意:

1-n是村庄,n+1-m+1是城堡,要从1-n+m,问最短时间

思路:

首先要为使用魔法做准备,这就需要求得沿路不经过城堡的所有路径(保证在最短状态),这就用到了floyd,然后是用spfa求用到魔法的最小时间

f[i][j]表示剩余i次到达j用时

如果不使用魔法能的到更短时间就不使用魔法

如果使用了魔法,那么首先路径必须<=l,其次次数有余

代码:

#include<cstdio>#include<iostream>#include<queue>#include<cstring>#include<map>using namespace std;const int INF = 0x3c3c3c3c;int n, m, k;const int maxn = 310;map<string, int> rs, dv;int p[maxn];int c[maxn][maxn];int f[maxn][maxn];int a[maxn];void ek(int ed) {memset(f, 0, sizeof(f));queue<int> q;int ans = 0;while(1) {memset(p, 0, sizeof(p));memset(a, 0, sizeof(a));a[0] = INF;q.push(0);while(!q.empty()) {int u = q.front();q.pop();for(int i=0; i<=ed; i++) {if(c[u][i]>f[u][i] && !a[i]) {a[i] = min(a[u], c[u][i]-f[u][i]);q.push(i);p[i] = u;}}}if(a[ed] == 0) break;for(int i=ed; i; i=p[i]) {f[p[i]][i] += a[ed];f[i][p[i]] -= a[ed];}ans += a[ed];}printf("%d\n", m-ans);}string str;int main() {int kase;string str;int adt = 0;int rid, did;scanf("%d", &kase);while(kase--) {adt = 0;memset(c, 0, sizeof(c));scanf("%d", &n);rs.clear();dv.clear();for(int i=1; i<=n; i++) {cin>>str;rs[str] = i;}scanf("%d", &m);for(int i=1; i<=m; i++) {cin>>str;if(dv[str] == 0) {dv[str] = i;}did = dv[str];c[0][did] += 1;cin>>str;if(rs[str] == 0) {adt++;rs[str] = n+adt;}rid = rs[str];c[did][rid+m] += 1;}    for(int i=m+1; i<=m+n; i++) c[i][m+n+adt+1] += 1;scanf("%d", &k);for(int i=0; i<k; i++) {cin>>str;rid = rs[str];cin>>str;c[rid+m][rs[str]+m] = INF;}ek(m+n+adt+1);if(kase) printf("\n");}return 0;}


0 0
原创粉丝点击