http://acm.hdu.edu.cn/showproblem.php?pid=4360
从昨天下午纠结到现在 交了20多次 。。
官方解题报告
1001
简单的图论题
每条边除了有边权以外,还有一个字母标记。标记可以是“LOVE”里面任意字符。
每个点,要拆成四个点,分别代表到达该点的标记为L,O,V,E的最短路。
第一步就是求最短路,直接spfa就可以了。
trick在于,至少要找到一个LOVE串,在只有一个节点的时候,有几条自环,至少必须走LOVE四条自环。此时,必须另外加一个节点表示开始节点。
还有一个trick就是距离可能超过int。
1 2 1314520 L
1 2 1314520 O
1 2 1314520 V
2 3 1314520 E
3 4 1314520 L
3 4 1314520 O
3 4 1314520 V
4 5 1314520 E
...
这种情况下1313个点,2624条边,每条边长度1314520,并且每条边都必须走,所以,超int了(至少signed不够)。
SPFA跑一趟就可以了。
这题将一个节点分解成四个点 标记的时候也是按照一个节点分成四个标记的 一个节点和字母组成一个点 将满足L->O->V->E这样路线而且可以更新距离 或者 可以更新LOVE数目 且没有被标记的那个点 入队 依次更新
1 #include <iostream> 2 #include<cstdio> 3 #include<string.h> 4 #include<queue> 5 using namespace std; 6 #define INF 200000000000000LL 7 struct node 8 { 9 int v; 10 int w,next; 11 char c; 12 }men[100000]; 13 struct mode 14 { 15 int nu,v; 16 }; 17 int first[2500],dd,f[100000][4],co[2500][4],a[300]; 18 __int64 s[2500][4]; 19 void init() 20 { 21 dd = 0; 22 memset(first,-1,sizeof(first)); 23 } 24 void add(int u,int v,int w,char c) 25 { 26 men[dd].v = v; 27 men[dd].w = w; 28 men[dd].c = c; 29 men[dd].next = first[u]; 30 first[u] = dd; 31 dd++; 32 } 33 void spfa(int n) 34 { 35 int i,j,k,m; 36 memset(f,0,sizeof(f)); 37 memset(co,0,sizeof(co)); 38 for(i = 1; i <= n; i++) 39 for(j = 0 ; j < 4 ; j++) 40 s[i][j] = INF; 41 queue<mode>q; 42 mode mm; 43 mm.v = 1; 44 mm.nu = 3; 45 co[1][3] = 0; 46 s[1][3] = 0; 47 f[1][3] =1; 48 q.push(mm); 49 while(!q.empty()) 50 { 51 mode kk = q.front(); 52 int nu = kk.nu; 53 int tk = kk.v; 54 q.pop(); 55 f[tk][nu] = 0; 56 for(i = first[tk] ; i!=-1 ; i = men[i].next) 57 { 58 int v = men[i].v; 59 int d = a[men[i].c]-1; 60 if((nu+1)%4==d) 61 { 62 if((s[v][d]>s[tk][nu]+men[i].w)||s[v][d]==0) 63 { 64 s[v][d] = s[tk][nu]+men[i].w; 65 co[v][d] = co[tk][nu]; 66 if(d==3) 67 co[v][d]++; 68 if(!f[v][d]) 69 { 70 f[v][d] = 1; 71 mm.v= v; 72 mm.nu = d; 73 q.push(mm); 74 } 75 } 76 else 77 if((s[v][d]==s[tk][nu]+men[i].w||s[v][d]==0)&&co[v][d]<=co[tk][nu]) 78 { 79 co[v][d] = co[tk][nu]; 80 if(d==3) 81 co[v][d]++; 82 if(!f[v][d]) 83 { 84 f[v][d] = 1; 85 mm.v= v; 86 mm.nu = d; 87 q.push(mm); 88 } 89 } 90 } 91 } 92 } 93 } 94 int main() 95 { 96 int i,j,k = 0,n,m,t,u,v,w; 97 char c; 98 a['L'] = 1; 99 a['O'] = 2; 100 a['V'] = 3; 101 a['E'] = 4; 102 scanf("%d",&t); 103 while(t--) 104 { 105 init(); 106 k++; 107 scanf("%d%d",&n,&m); 108 for(i = 1 ; i <= m ;i++) 109 { 110 scanf("%d%d%d %c",&u,&v,&w,&c); 111 add(u,v,w,c); 112 add(v,u,w,c); 113 } 114 spfa(n); 115 printf("Case %d: ",k); 116 if(co[n][3]==0||s[n][3]==INF) 117 printf("Binbin you disappoint Sangsang again, damn it!\n"); 118 else 119 { 120 printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",s[n][3],co[n][3]); 121 } 122 } 123 return 0; 124 }