刚开始想用dfs,后来想想,这要是用dfs的话节点之间的边过多那么,一方面容易爆栈,另一方面容易超时。
转换另一种思路,最段路径。
只有52个节点,用Dijkstra算法,
刚开始想这倒着算,但要是遇到城镇的化不好进行计算。
还是正着算好,但正着算又该如何计算呢,吴永辉老师告诉我们,直接二分模拟就好。从p到2的20次方,二分最多进行20次就好了。
但还得注意二分的方法。。。。。
害得我wa了,还是吴老师的二分写得好。
在迪杰斯特拉算法中,模拟他的思想,对于本题,选取最大的中间节点以他为跳板进行松弛,
ac代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3fffffff
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;
//#define debug
inline int trans(char ch){
if(islower(ch)) return ch-'a'+27;
else return ch-'A'+1;
}
bool mmp[55][55];
int check(int a,int b,int w){
int g[55];
bool vis[55];
mm(g,0);mm(vis,0);
g[a]=w;
int cnt=0;
for(int k=0;k<51;k++){
int next;
int maxn=0;
for(int i=1;i<=52;i++){
if(!vis[i]&&maxn<g[i]){
maxn=g[i];next=i;
}
}
vis[next]=1;
for(int i=1;i<=52;i++){
if(mmp[next][i]){
g[i]=max(g[i],maxn-(i<27?(maxn-1)/20+1:1));
}
}
}
return g[b];
}
int main()
{
#ifdef debug
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif // debug
int n;
int casei=1;
while(scanf("%d",&n)!=EOF&&n!=-1){
mm(mmp,0);
while(n--){
char c1,c2;
scanf(" %c %c",&c1,&c2);
int a=trans(c1),b=trans(c2);
mmp[a][b]=mmp[b][a]=1;
}
int v,c1,c2;
scanf("%d %c %c",&v,&c1,&c2);
int a=trans(c1),b=trans(c2);
int l=v,r=1<<20;
while(l!=r){
int mid=(l+r-1)>>1;
if(check(a,b,mid)>=v) r=mid;
else l=mid+1;
}
printf("Case %d: %d\n",casei++,l);
}
return 0;
}