@Asuna
2017-02-21T19:45:00.000000Z
字数 4696
阅读 844
题解
题意:寻找最短的从商店到赛场的路线。
题解:最短路模版题。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;
}