Description
Input
Output
Sample Input
1 4 10000 3 2 2 8000 3 5000 1000 2 1 4 200 3000 2 1 4 200 50 2 0
Sample Output
5250
Source
这个题好像是大半年前就看过了,为什么到现在才会==就不能上点心学习吗???
说题意:中文题没啥好说的。限制范围的枚举很容易就能想到。需要注意以下几点:
1.反向建图,因为酋长不是起点是终点!
2.没有必要再加一个点模仿网络流的”汇点“,更何况知道了酋长是终点之后,就更没有理由自作聪明的加一个汇点。而那个不需要换的自身的值最后加上就好啦~
3.酋长未必是地位最高,所以要以酋长的等级来限制循环的条件
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=133; const int inf=0x3f3f3f3f; bool vis[maxn]; int pre[maxn],lowcost[maxn],cost[maxn][maxn],val[maxn],rank[maxn]; void dijkstra(int cost[][maxn],int n,int beg) { for(int i=0;i<n;i++) { lowcost[i]=inf;vis[i]=false;pre[i]=-1; } lowcost[beg]=0; for(int j=0;j<n;j++) { int k=-1; int Min=inf; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[i]<Min) { Min=lowcost[i]; k=i; } if(k==-1)break; vis[k]=true; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]) { lowcost[i]=lowcost[k]+cost[k][i]; pre[i]=k; } } } int tmp[maxn][maxn]; int main() { freopen("cin.txt","r",stdin); int m,n; while(~scanf("%d%d",&m,&n)) { memset(cost,inf,sizeof(cost)); int maxn=0,minn=inf; for(int i=0;i<n;i++) { int x; scanf("%d%d%d",&cost[n][i],&rank[i],&x); if(rank[i]>maxn)maxn=rank[i]; if(rank[i]<minn)minn=rank[i]; while(x--) { int t,v; scanf("%d%d",&t,&v);t--; if(v<cost[i][t]) cost[i][t]=v; } } int ans=inf; for(int k=max(0,rank[0]-m);k<=rank[0]+m;k++) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(rank[i]>=k&&rank[i]<=k+m&&rank[j]>=k&&rank[j]<=k+m) tmp[i][j]=cost[i][j]; else tmp[i][j]=inf; } dijkstra(tmp,n,0); for(int i=0;i<n;i++) if(ans>lowcost[i]+cost[n][i]) ans=lowcost[i]+cost[n][i]; } printf("%d\n",ans); } return 0; }