[USACO09DEC]牛收费路径Cow Toll Paths

题目大意:给定一个无向图,求出一条路径,使得边权和加上点权和最小,多组询问

n<=250 m<=10000

多组询问,数据范围这么小,很显然就是floyd了,但是这个点权着实让人讨厌哇。。。

我们重新回想一遍floyd算法的原理:i到j有两种可能:直接到和借助中间接口k,所以取一个min就行了

我们再往下细细的想一下,k代表的是中间的接口,而且k的枚举顺序是任意的?

显然是任意的!突破口就在这:我们可以肆意的修改k的枚举顺序!

所以,这道题就解决了,我们只要从小到大枚举k,跑flyod,点权最大值利用min(c[i],c[j],c[k])来维护就行了!

正确性?

当我们枚举到一个k的时候,就代表路径中除了i,j以外没有任何数可能比k大,所以我们在三个中取一个min就行了

时间复杂度:O(n^3)

注意处理细节:例如枚举后顺序改变等

最后,附上本题代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 //Debug Yufenglin
 8 #define dej printf("Running\n");
 9 #define dep1(x) cout<<#x<<"="<<x<<endl;
10 #define dep2(x,y) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<endl;
11 #define dep3(x,y,z) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<' '<<#z<<"="<<z<<endl;
12 
13 //Standfor Yufenglin
14 #define LL long long
15 #define LB long double
16 #define reg register
17 #define il inline
18 #define inf 1000000000
19 #define maxn 250
20 #define maxm 1005
21 
22 struct pot
23 {
24     int v,id;
25 };
26 int n,m,q;
27 pot c[maxn+5];
28 int dis[maxn+5][maxn+5],f[maxn+5][maxn+5],pre[maxn+5];
29 
30 bool cmp(pot x,pot y)
31 {
32     if(x.v==y.v) return x.id<y.id;
33     return x.v<y.v;
34 }
35 int main()
36 {
37     scanf("%d%d%d",&n,&m,&q);
38     for(int i=1;i<=n;i++)
39     {
40         scanf("%d",&c[i].v);
41         c[i].id=i;
42     }
43     sort(c+1,c+n+1,cmp);
44     for(int i=1;i<=n;i++)
45     {
46         pre[c[i].id]=i;
47     }
48     memset(dis,0x1f,sizeof(dis));
49     memset(f,0x1f,sizeof(f));
50     for(int i=1;i<=m;i++)
51     {
52         int x,y,z;
53         scanf("%d%d%d",&x,&y,&z);
54         dis[pre[x]][pre[y]]=dis[pre[y]][pre[x]]=min(dis[pre[x]][pre[y]],z);
55     }
56     for(int i=1;i<=n;i++) dis[i][i]=0;
57     for(int k=1;k<=n;k++)
58     {
59         for(int i=1;i<=n;i++)
60         {
61             for(int j=1;j<=n;j++)
62             {
63                 if(i==j) continue;
64                 dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
65                 f[i][j]=min(f[i][j],dis[i][j]+max(c[i].v,max(c[j].v,c[k].v)));
66             }
67         }
68     }
69     for(int i=1;i<=q;i++)
70     {
71         int x,y;
72         scanf("%d%d",&x,&y);
73         printf("%d\n",f[pre[x]][pre[y]]);
74     }
75     return 0;
76 }

猜你喜欢

转载自www.cnblogs.com/yufenglin/p/10702998.html