很入门的最短路

好多做法相通的题没咋写别的做法,思路都差不多,刚学感觉带环的比较恶心,但是很重要。后续再补一波题会改会删。
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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值