@Asuna
2017-02-21T11:45:00.000000Z
字数 4696
阅读 971
题解
题意:寻找最短的从商店到赛场的路线。
题解:最短路模版题。mark一下模版。
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
参考代码:
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int d[110],w[110][110],vis[110],n,m,a,b,c;void dijkstra(int s){for (int i=1; i<=n; i++)d[i]=10000000;d[s] = 0;memset(vis, 0, sizeof(vis));for (int i=1; i<=n; i++){int u=-1;for (int j=1; j<=n; j++)if (!vis[j]){if (u==-1 || d[j]<d[u]) u=j;}vis[u]=1;for (int j=1; j<=n; j++)if (!vis[j]){int tmp=d[u]+w[u][j];if (tmp<d[j]) d[j]=tmp;}}}int main(){while(cin>>n>>m){if (n==0 && m==0) break;for (int i=1; i<=n; i++){w[i][i]=10000000;for (int j=i+1; j<=n; j++)w[i][j]=w[j][i]=100000000;}for (int i=0; i<m; i++){cin>>a>>b>>c;w[a][b]=w[b][a]=c;}dijkstra(1);cout<<d[n]<<endl;}return 0;}
题意:已知从一个农场到另一个农场的一些通道和所需的时间,一些虫洞(虫洞是单向通道,可以回到前一段时间),问这个人能否回到起始地方。
题解:构造出图,将农田抽象成点,通道抽象成边,这样可以将虫洞抽象成负边,判断是否存在负环,这样就可以用Bellman_Ford求解。
参考代码:
#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<algorithm>using namespace std;struct node{int u,v,w;}que[10010];int t,n,m,wh,cnt,inf=999999999,dis[5010],t1,t2,t3;bool bellman_ford(){memset(dis,inf,sizeof(dis));dis[1]=0;int flag,a,b,c;for (int i=1; i<n; i++){flag=0;for (int j=0; j<cnt; j++){a=que[j].u;b=que[j].v;c=que[j].w;if (dis[b]>dis[a]+c){dis[b]=dis[a]+c;flag=1;}}if(!flag)break;}for (int j=0; j<cnt; j++){a=que[j].u;b=que[j].v;c=que[j].w;if(dis[b]>dis[a]+c)return true;}return false;}int main(){cin>>t;while (t--){cnt=0;cin>>n>>m>>wh;for(int i=1; i<=m; i++){cin>>t1>>t2>>t3;que[cnt].u=t1;que[cnt].v=t2;que[cnt].w=t3;cnt++;que[cnt].u=t2;que[cnt].v=t1;que[cnt].w=t3;cnt++;}for (int i=m+1; i<=m+wh; i++){cin>>t1>>t2>>t3;que[cnt].u=t1;que[cnt].v=t2;que[cnt].w=-t3;cnt++;}if (bellman_ford()) cout<<"YES"<<endl;else cout<<"NO"<<endl;}return 0;}
题意:每个人传递消息同时进行,求最后一个人知道消息的最短时间。
题解:先枚举每个人为起点的情况,然后这个情况下求每个人知道消息的最短时间,然后遍历一遍找到最大的那个,就是最后一个人收到消息的时间了。然后比较出所以情况中最后一个人知道消息的时间的最小值。
参考代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;int n,dis[10010],a[1010][1010],book[10010],minn,v,m,x,y,maxx,k;void dijstra(int s){for (int i=1; i<=n; i++) dis[i]=99999999;dis[s]=0;for (int i=1; i<=n; i++)book[i]=0;for (int i=1; i<=n; i++){int minn=99999999;for (int j=1; j<=n; j++){if (dis[j]<minn && book[j]==0){minn=dis[j];v=j;}}book[v]=1;for (int j=1; j<=n; j++){if (book[j]==0){if (dis[j]>dis[v]+a[v][j]){dis[j]=dis[v]+a[v][j];}}}}return;}int main(){while(cin>>n){if (n==0) break;for (int i=1; i<=n; i++){for (int j=1; j<=n; j++){if (i<=j)a[i][j]=a[j][i]=99999999;}}for (int i=1; i<=n; i++){cin>>m;for(int j=1; j<=m; j++){cin>>x>>y;a[i][x]=y;}}minn=99999999;k=0;for (int i=1; i<=n; i++){dijstra(i);maxx=0;for (int j=1; j<=n; j++){if (j!=i){if (dis[j]>maxx) maxx=dis[j];}}//cout<<maxx<<" "<<minn<<endl;if (maxx<minn){minn=maxx;k=i;}}if (k!=0) cout<<k<<" "<<minn<<endl;else cout<<"disjoint"<<endl;}return 0;}
题意:娶到酋长女儿的最小代价,即到达终点的最短距离。
题解:枚举的最小等级,枚举过程中把小于这个等级,差距大于m的删去。
参考代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int w[110][110],n,m,x,k,minn,l[110],p[110],dis[110],vis[110],within[110],boss,cost,ans;int dijkstra (){int k,minn;memset(vis,0,sizeof(vis));for (int i=1; i<=n; i++)dis[i]=w[1][i];dis[1]=0;vis[1]=1;for (int i=1; i<=n; i++){minn=999999999;for (int j=1; j<=n; j++){if (!vis[j] && within[j] && dis[j]<minn){k=j;minn=dis[j];}}if (minn==999999999)break;vis[k]=1;dis[k]=minn;for (int j=1; j<=n; j++)if (!vis[j] && within[j] && dis[k]+w[k][j]<dis[j])dis[j]=dis[k]+w[k][j];}minn=999999999;for (int i=1; i<=n; i++)if (dis[i]+p[i]<minn && vis[i])minn=dis[i]+p[i];return minn;}int main(){cin>>m>>n;for (int i=1; i<=n; i++)for (int j=1; j<=n; j++)if (i==j) w[i][j]=0;else w[i][j]=999999999;for (int i=1; i<=n; i++){cin>>p[i]>>l[i]>>x;for (int j=0; j<x; j++){cin>>k;cin>>w[i][k];}}boss=l[1];ans=999999999;for (int i=0; i<=m; i++){memset(within,0,sizeof(within));for (int j=1; j<=n; j++){if (boss-l[j]<=m-i && l[j]-boss<=i)within[j]=1;}cost=dijkstra();if (cost<ans) ans=cost;}cout<<ans<<endl;return 0;}
题意:给定一个有向图,多个起点,一个终点,求起点到终点的最短路。
题解:将0看成出发点,将n个能选择的点看做事0的相邻并且花费为0的点,那么就是求0到S的最小花费了。
参考代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,s,x,y,t,w[1005][1005],vis[1005],dis[1005];void dijkstra(){int minn,k;memset(vis,0,sizeof(vis));vis[0]=1;for (int i=0; i<=n; i++)dis[i]=w[0][i];for (int i=0; i<=n; i++){minn=100000000;for (int j=0; j<=n; j++){if (dis[j]<minn && !vis[j]){k=j;minn=dis[j];}}vis[k]=1;for (int j=0; j<=n; j++){if (dis[k]+w[k][j]<dis[j] && !vis[j])dis[j]=dis[k]+w[k][j];}}}int main(){while(cin>>n>>m>>s){for (int i=0; i<=n; i++)for (int j=0; j<=n; j++)w[i][j]=100000000;for (int i=1; i<=m; i++){scanf("%d%d%d",&x,&y,&t);if (t<w[x][y])w[x][y]=t;}cin>>m;for (int i=1; i<=m; i++){scanf("%d",&x);w[0][x]=0;}dijkstra();if (dis[s]==100000000) cout<<-1<<endl;else cout<<dis[s]<<endl;}return 0;}