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