好多做法相通的题没咋写别的做法,思路都差不多,刚学感觉带环的比较恶心,但是很重要。后续再补一波题会改会删。
1.HDU1874
注意点下标从0开始。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int N=220;
const int INF=0x3f3f3f3f;
int dist[N],g[N][N];
bool st[N];
int n,m,s,ed;
int dij()
{
memset(dist,0x3f,sizeof dist);
dist[s]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=0;j<n;j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=0;j<n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
if(dist[ed]==0x3f3f3f3f)
return -1;
return dist[ed];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(g,0x3f,sizeof g);
memset(st,false,sizeof st);
while (m -- )
{
int x,y,z;
cin>>x>>y>>z;
if(g[x][y]>z)
g[x][y]=g[y][x]=z;
}
cin>>s>>ed;
cout<<dij()<<endl;
}
return 0;
}
2 HDU1548
宽广搜专题中有这道题,将边权看成1找起点到终点的最短路即为步数。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=210;
const int INF=0x3f3f3f3f;
int g[N][N],dist[N];
bool st[N];
int n,a,b;
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[a]=0;
for(int i=1;i<=n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(st[j]==false &&(t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=1;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
}
int main()
{
while(cin>>n)
{
if(n==0)
break;
cin>>a>>b;
memset(g,0x3f,sizeof g);
for(int i=1;i<=n;i++)
{
int k;
cin>>k;
if(i+k<=n)
g[i][i+k]=1;
if(i-k>=1)
g[i][i-k]=1;
}
memset(st,false,sizeof st);
dijkstra();
if(dist[b]==INF)
cout<<-1<<endl;
else
cout<<dist[b]<<endl;
}
return 0;
}
3 HDU2544
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
const int M=10010;
int dist[N],g[N][N],n,m;
bool st[N];
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=1;i<=n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=1;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
return dist[n];
}
int main()
{
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
memset(g,0x3f,sizeof g);
memset(st,false,sizeof st);
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
if(g[x][y]>z)
g[x][y]=z,g[y][x]=z;//本质是无向图(边可能反着给)
}
cout<<dijkstra()<<endl;
}
return 0;
}
4 HDU3790
案例都过了但都t了,而且一开始根本找到不错误在哪里,我甚至怀疑板子是错的我也没觉得我板子套错了,这个题确实提醒我以后要注意这些细节…
①朴素dij:tle
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1010;
const int INF=0x3f3f3f3f;
int g[N][N],dist[N],cost[N],gg[N][N];
bool st[N];
int n,m,s,f;
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
memset(cost,0x3f,sizeof dist);
dist[s]=0;
cost[s]=0;
for(int i=1;i<=n;i++)
{
if(st[f]==true)
break;
int t=-1;
for(int j=1;j<=n;j++)
{
if(st[j]==false &&(t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=1;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
{
dist[j]=dist[t]+g[t][j];
cost[j]=cost[t]+gg[t][j];
}
else if(dist[j]==dist[t]+g[t][j])
{
if(cost[j]>cost[t]+gg[t][j])
{
cost[j]=cost[t]+gg[t][j];
}
}
}
}
return;
}
int main()
{
while(cin>>n>>m)
{
if(n==0 && m==0)
break;
memset(g,0x3f,sizeof g);
memset(gg,0x3f,sizeof gg);
memset(st,false,sizeof st);
for(int i=1;i<=m;i++)
{
int x,y,d,p;
cin>>x>>y>>d>>p;
if(g[x][y]>d)
{
g[x][y]=d;
g[y][x]=d;
gg[x][y]=p;
gg[y][x]=p;
}
else if(g[x][y]==d)
{
if(gg[x][y]>p)
{
gg[x][y]=p;
gg[y][x]=p;
}
}
}
cin>>s>>f;
dijkstra();
cout<<dist[f]<<' '<<cost[f]<<endl;
}
return 0;
}
②堆优化dij:首先HDU太古老识别不出优先队列模拟的堆,但前面n^2铁t了,我开始以为是不是数据组数太多了???n=1000那最少也1e3组数据,这么算优化一波这n组每组mlogn也超时…
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int,int> PII;
const int N=1010;
const int M=1e5+10;
const int INF=0x3f3f3f3f;
int dist[N],p[N];
int e[M],ne[M],w[M],ww[M],h[N],idx;
bool st[N];
int n,m,s,f;
void add(int a,int b,int c,int d)
{
e[idx]=b;
w[idx]=c;
ww[idx]=d;
ne[idx]=h[a];
h[a]=idx++;
}
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[s]=0;
p[s]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push({0,1});
while(heap.size())
{
PII t=heap.top();
heap.pop();
int id=t.second,dis=t.first;
if(st[id]==true)
continue;
st[id]=true;
for(int i=h[id];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dis+w[i])
{
dist[j]=dis+w[i];
heap.push({dist[j],j});
p[j]=p[id]+ww[i];
}
}
}
}
int main()
{
while(cin>>n>>m)
{
if(n==0 && m==0)
break;
memset(h,-1,sizeof h);
memset(st,false,sizeof st);
while(m--)
{
int x,y,a,b;
cin>>x>>y>>a>>b;
add(x,y,a,b);
add(y,x,a,b);
}
cin>>s>>f;
dijkstra();
cout<<dist[f]<<' '<<p[f]<<endl;
}
return 0;
}
③SPFA:也t了但是这个甚至在意料之中,至此我只是以为spfa被卡了,很正常。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=10100;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
int dist[N],cost[N];
bool st[N];
int e[M],ne[M],w[M],c[M],h[N],idx;
int n,m,s,f;
void add(int x,int y,int d,int p)
{
e[idx]=y;
w[idx]=d;
c[idx]=p;
ne[idx]=h[x];
h[x]=idx++;
}
void spfa()
{
memset(dist,0x3f,sizeof dist);
memset(dist,0x3f,sizeof dist);
dist[s]=0;
cost[s]=0;
queue<int>q;
q.push(s);
st[s]=true;
while(q.size())
{
int t=q.front();
st[t]=false;
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[t]+w[i] || (dist[j]==dist[t]+w[i] && cost[j]>cost[t]+c[i]))
{
dist[j]=dist[t]+w[i];
cost[j]=cost[t]+c[i];
if(st[j]==false)
{
q.push(j);
st[j]=true;
}
}
}
}
}
int main()
{
while(cin>>n>>m)
{
if(n==0 && m==0)
return 0;
memset(h,-1,sizeof h);
memset(st,false,sizeof st);
while(m--)
{
int x,y,d,p;
cin>>x>>y>>d>>p;
add(x,y,d,p);
add(y,x,d,p);
}
cin>>s>>f;
spfa();
cout<<dist[f]<<' '<<cost[f]<<endl;
}
return 0;
}
优化下又交了n发后发现全崩我看傻了,直到刷完了两集电视剧,灵感突然闪现是不是他娘的cin的问题?我改了一下scanf,真红!(在这儿我不怕红色!!!以后再也不敢随便用cin了…)
可以看一下只用一次cin输入四个元素和只用scanf在被卡cin情况下的时间差距。
5 HDU2066
参考一个dalao的想法,把问题变成从家出发到可以到达的S个城市的距离为0,从家(0号点)开始搜最短路,单源只需要一次dij,减少了多源的时间复杂度。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N=1010;
int T,S,D,n=-1;
int g[N][N];
int dist[N],d[N];
bool st[N];
void Dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[0]=0;
for(int i=0;i<=n;i++)
{
int t=-1;
for(int j=0;j<=n;j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=0;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
}
int main()
{
while(~scanf("%d%d%d",&T,&S,&D))
{
memset(g,0x3f,sizeof g);
memset(st,false,sizeof st);
while(T--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
n = max(max(n,x),y);
if(z<g[x][y])
g[x][y] = g[y][x] = z;
}
int minn = inf;
while(S--)
{
int s;
scanf("%d",&s);
g[0][s] = g[s][0] = 0;
}
Dijkstra();
for(int i=0;i<D;i++)
{
int d;
scanf("%d",&d);
minn = min(minn,dist[d]);
}
printf("%d\n",minn);
}
return 0;
}
6 HDU2112
公交车数量可形象理解为边数(可重复,把站台看成点就明白了),板子题,将string映射成int型的点号再找最短路。
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=160;
int n,m,dist[N],g[N][N];//稠密图
bool st[N];
string start,ed;
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=1;i<=n-1;++i)
{
int t=-1;
for(int j=1;j<=n-1;++j)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=1;j<=n-1;++j)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
if(dist[2]==INF)
return -1;
return dist[2];
}
int main()
{
while(scanf("%d",&m) && m!=-1)
{
memset(g,0x3f,sizeof g);
memset(st,false,sizeof st);
map<string,int>mp;
n=1;
cin>>start>>ed;
if(mp[start]==0)
mp[start]=n++;
if(mp[ed]==0)
mp[ed]=n++;
while(m--)
{
string aa,bb;
int dis;
cin>>aa>>bb>>dis;
if(mp[aa]==0)
mp[aa]=n++;
if(mp[bb]==0)
mp[bb]=n++;
g[mp[aa]][mp[bb]]=g[mp[bb]][mp[aa]]=min(g[mp[aa]][mp[bb]],dis);
}
if(start==ed)//原地转圈你座什么公交?
cout<<"0"<<endl;
else
cout<<dijkstra()<<endl;
}
return 0;
}
7 HDU1217
无脑floyd
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=40;
int n,m,dist[N];
double g[N][N];//只给了点大概率稠密图
bool floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(g[i][j]<g[i][k]*g[k][j])//保证路径权值乘法最大的路绕一圈>1就行
g[i][j]=g[i][k]*g[k][j];
}
}
}
for(int i=1;i<=n;i++)
{
if(g[i][i]>1)
return true;
}
return false;
}
int main()
{
int cnt=1;
while(scanf("%d",&n) && n)
{
memset(g,0x3f,sizeof g);
map<string,int>mp;
for(int i=1;i<=n;i++)
{
string x;
cin>>x;
mp[x]=i;
}
cin>>m;
for(int i=1;i<=m;i++)
{
string x,y;
double z;
cin>>x>>z>>y;
g[mp[x]][mp[y]]=z;
}
printf("Case %d: ",cnt++);
if(floyd())
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}
8 HDU1245
开始想不通,按单源多汇想了,看了题解其实不难。将岛看做下标为0的起点,将岸看做下标为n+1的终点,还有n个鳄鱼,共n+2个点,模型转化出来就是板子了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include <queue>
using namespace std;
const int maxn = 120;
const int INF = 0x3f3f3f3f;
double dist[maxn],g[maxn][maxn],d;
int n,tot,step[maxn];
bool st[maxn];
struct node
{
double x,y;
}cur[maxn];//记录当前号点的坐标
void init()
//初始化n+2个点到源点的距离为INF、标志为未走过、走到当前点的步数为0
{
tot=0;
for(int i=0;i<=n+5;i++)
{
dist[i] = INF;
st[i] = false;
step[i] = 0;
for(int j=0;j<=n+5;j++)
g[i][j] = INF;
}
//初始化地图上每两个鳄鱼的距离为INF
}
void spfa()
{
dist[0]=0;
queue<int>q;
q.push(0);
st[0]=true;
while(q.size())
{
int t=q.front();
st[t]=false;
q.pop();
for(int i=0;i<=n;i++)
{
if(g[t][i]!=INF)
{
if(dist[i]>dist[t]+g[t][i] || (dist[i]==dist[t]+g[t][i] && step[i]>step[t]+1))
{
dist[i]=dist[t]+g[t][i];
step[i]=step[t]+1;
if(st[i]==false)
{
q.push(i);
st[i]=true;
}
}
}
}
}
}
int main()
{
while(~scanf("%d%lf",&n,&d))
{
init();
for(int i=1;i<=n;i++)
{
double x,y;
scanf("%lf%lf",&x,&y);
double dd=sqrt(x*x+y*y);//到源点的,要减半径
if(dd>7.5)//保证前提是鳄鱼在河里,不加会超时
{
cur[++tot].x=x;
cur[tot].y=y;
if(dd-7.5<=d)
{
g[0][tot]=dd-7.5;
g[tot][0]=dd-7.5;
}
}
}
n=tot+1;//湖外的岸也算一个点
for(int i=1;i<n;i++)
{
if(fabs(cur[i].x+50)<=d || fabs(cur[i].x-50)<=d || fabs(cur[i].y-50)<=d || fabs(cur[i].y+50)<=d)//再走一步就能上岸的点全标记距离
{
g[i][n]=g[n][i]=min(min(fabs(cur[i].x+50),fabs(cur[i].x-50)),min(fabs(cur[i].y+50),fabs(cur[i].y-50)));
}
for(int j=i+1;j<n;j++)//鳄鱼间距离(j=i+1的双重循环后按字典序标记,省去了n^2中重复的赋值)
{
double dd=sqrt((cur[i].x-cur[j].x)*(cur[i].x-cur[j].x)+(cur[i].y-cur[j].y)*(cur[i].y-cur[j].y));
if(dd<=d)
g[i][j]=g[j][i]=dd;
}
}
spfa();
if(dist[n]==INF)//一定无负权
cout<<"can't be saved"<<endl;
else
printf("%.2lf %d\n",dist[n],step[n]);//注意格式
}
return 0;
}
9 HDU1317
这题思路挺乱。
①在到每一个点后体力都>0的前提下,只需要知道到终点的最大可获得多少能量,若>0则至少存在一条路可以通关。
②若路径上有环,则一定不是负环(此处求最大路,有负环也不会走到),一定是正环,那么需要用num数组判断第i个点是否在正环上,若在,则如果此点到终点是连通的,那么一定可以通关(在正环上兜圈总体力滚雪球)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
using namespace std;
const int N=110;
const int inf=-0x3f3f3f3f;//用于初始化,便于求最大路
int n,m;
int e[N],d[N],num[N];
//e:第i个点的能量值
//d:源点到当前点的路径上点权之和
//num:当前点进队几次,若>=n则该点在环上
bool reach[N][N];//判断两点的连通性
bool mp[N][N];//存原图
void init()
{
memset(reach,false,sizeof(reach));
memset(mp,false,sizeof(mp));
fill(d,d+N,inf);//最大路初值是负的,最好别memset
memset(num,0,sizeof(num));
}
void floyd()//判连通
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
reach[i][j]=reach[i][j] || (reach[i][k] && reach[k][j]);
}
bool spfa(int s,int d[])
{
queue<int>q;
q.push(s);
d[s]=100;//初始生命100
while(q.size())
{
int t=q.front();
q.pop();
num[t]++;
if(num[t]>=n)//先判有环(且一定为正环,因为求最大路)
return reach[t][n];//当前点处有正环,若当前点能到终点n则一定可以完成
for(int i=1;i<=n;i++)//无环情况
{
if(mp[t][i]==true && d[i]<d[t]+e[i]&&d[t]+e[i]>0)//求极大路时求到任何点的权值和都应>0
{
d[i]=d[t]+e[i];
q.push(i);
}
}
}
return d[n]>0;//到最后一个点>0说明至少有一最大路可以使游戏成功
}
int main()
{
while(scanf("%d",&n))
{
if(n==-1)
break;
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d",&e[i],&m);
for(int j=1;j<=m;j++)
{
int v;
scanf("%d",&v);
mp[i][v]=true;
reach[i][v]=true;
}
}
floyd();
if(spfa(1,d))
printf("winnable\n");
else
printf("hopeless\n");
}
return 0;
}
10 HDU1535
n=m=1e6很大,如果每个点为起点都找下最短路即使spfa最好时间也有O(nm)也会t,思路为正着加一次所有最短路径,再把所有边都反过来加一次就是所有点能到1号起点的最短路径,两次相加就能求出往返路径。
(这里我没传参因为考虑大概率是稀疏图所以用的邻接矩阵,参数太多有点不好传索性最笨的方法写了两遍。。。)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=1e6+10;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
int dist1[N],dist2[N],p,q;
long long sum;
bool st1[N],st2[N];
int n;
int e1[M],ne1[M],w1[M],h1[N],idx1;
int e2[M],ne2[M],w2[M],h2[N],idx2;
void add1(int a,int b,int c)
{
e1[idx1]=b;
w1[idx1]=c;
ne1[idx1]=h1[a];
h1[a]=idx1++;
}
void add2(int a,int b,int c)
{
e2[idx2]=b;
w2[idx2]=c;
ne2[idx2]=h2[a];
h2[a]=idx2++;
}
long long spfa1()
{
memset(dist1,0x3f,sizeof dist1);
queue<int>q;
dist1[1]=0;
q.push(1);
st1[1]=true;
while(q.size())
{
int t=q.front();
st1[t]=false;
q.pop();
for(int i=h1[t];i!=-1;i=ne1[i])
{
int j=e1[i];
if(dist1[j]>dist1[t]+w1[i])
{
dist1[j]=dist1[t]+w1[i];
if(st1[j]==false)
{
q.push(j);
st1[j]=true;
}
}
}
}
long long summ=0;
for(int i=1;i<=p;i++)
{
summ+=dist1[i];
}
return summ;
}
long long spfa2()
{
memset(dist2,0x3f,sizeof dist2);
queue<int>q;
dist2[1]=0;
q.push(1);
st2[1]=true;
while(q.size())
{
int t=q.front();
st2[t]=false;
q.pop();
for(int i=h2[t];i!=-1;i=ne2[i])
{
int j=e2[i];
if(dist2[j]>dist2[t]+w2[i])
{
dist2[j]=dist2[t]+w2[i];
if(st2[j]==false)
{
q.push(j);
st2[j]=true;
}
}
}
}
long long summ=0;
for(int i=1;i<=p;i++)
{
summ+=dist2[i];
}
return summ;
}
int main()
{
cin>>n;
while (n -- )
{
cin>>p>>q;
memset(h1,-1,sizeof h1);
memset(h2,-1,sizeof h2);
memset(st1,false,sizeof st1);
memset(st2,false,sizeof st2);
while(q--)
{
int x,y,z;
cin>>x>>y>>z;
add1(x,y,z);
add2(y,x,z);
}
sum=spfa1()+spfa2();
cout<<sum<<endl;
}
}
11 HDU1546
判断条件加边。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
using namespace std;
const int N=1e3+10;
const int INF=0x3f3f3f3f;
map<string,int>mp;
int dist[N],g[N][N],p,q;
bool st[N];
int n;
int val[N];
char str[N][N];
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=1;i<=n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=1;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
}
int main()
{
while(scanf("%d",&n))
{
if(n==0)
break;
memset(st,false,sizeof st);
map<string,int>mp;
for(int i=1;i<=n;i++)
cin>>val[i]>>str[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int l=strlen(str[i]);
if(i==j)
g[i][j]=0;
else if(str[j][0] == str[i][l-4] && str[j][1] == str[i][l-3] &&str[j][2] == str[i][l-2]&&str[j][3] == str[i][l-1])
g[i][j]=val[i];
else
g[i][j]=INF;
}
}
dijkstra();
if(n==1)
cout<<-1<<endl;
else if(dist[n]==INF)
cout<<-1<<endl;
else
cout<<dist[n]<<endl;
}
return 0;
}
12 HDU2680
同5。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
const int N=1e3+10;
const int INF=0x3f3f3f3f;
int dist[N],g[N][N];
bool st[N];
int n,m,s;
void init()
{
memset(g,0x3f,sizeof g);
memset(dist,0x3f,sizeof dist);
memset(st,false,sizeof st);
}
int dij()
{
memset(dist,0x3f,sizeof dist);
dist[0]=0;
for(int i=0;i<=n;i++)
{
int t=-1;
for(int j=0;j<=n;j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=0;j<=n;j++)
{
if(dist[j]>dist[t]+g[t][j])
dist[j]=dist[t]+g[t][j];
}
}
if(dist[s]==0x3f3f3f3f)
return -1;
return dist[s];
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&s))
{
init();
while (m -- )
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(g[x][y]>z)
g[x][y]=z;
}
int w;
scanf("%d",&w);
while(w--)
{
int x;
scanf("%d",&x);
g[0][x]=0;
}
cout<<dij()<<endl;
}
return 0;
}
13 HDU2923
带模拟的大水题。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int N=1e2+10;
const int INF=0x3f3f3f3f;
int dist[N],g[N][N];
bool st[N];
int n,c,r;
map<string,int>mp;
string ans[1010];
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
}
int main()
{
int cnt=0;
while(scanf("%d%d%d",&n,&c,&r))
{
if(n==0 && c==0 && r==0)
break;
cnt++;
mp.clear();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
g[i][j]=0;
else
g[i][j]=g[j][i]=INF;
}
}
int m=0;
for(int i=0;i<=c;i++)//第二行输入c+1个单词,第一个是车库单词对应的位置,剩下c个是破车单子对应的位置
{
cin>>ans[i];//输入边对应的字符串
if(!mp[ans[i]])//从0开始没编号的点编号
mp[ans[i]]=++m;
}
while(r--)//r条路
{
string a,b,c;
int tem=0;
int f1=0,f2=0;
cin>>a>>b>>c;
if(mp[a]==0)
mp[a]=++m;
if(mp[c]==0)
mp[c]=++m;
if(b[0]=='<')//反向路
f1=1;
int l=b.size();
if(b[l-1]=='>')//正向路
f2=1;
for(int j=0;j<l;j++)
{
if(b[j]>='0' && b[j]<='9')
tem=(b[j]-'0'+tem)*10;//路长(多乘了10要除掉)
}
if(f1==1 && tem/10<g[mp[a]][mp[c]])
g[mp[a]][mp[c]]=tem/10;
if(f2==1 && tem/10<g[mp[c]][mp[a]])
g[mp[c]][mp[a]]=tem/10;
}
floyd();
int sum=0;
for(int i=1;i<=c;i++)
{
sum+=g[mp[ans[0]]][mp[ans[i]]];
sum+=g[mp[ans[i]]][mp[ans[0]]];
}
printf("%d. %d\n",cnt,sum);
}
return 0;
}