您的位置:首页 > 其它

uva10269

2016-07-27 18:57 330 查看
题意:

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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: