[kuangbin带你飞]专题四 最短路练习H,I,J

时间:2021-07-10 12:29:14

H题:
http://poj.org/problem?id=3660

题意:

给你n个点,m个关系,每个关系说明了u在v前
问能确定下来位置的点有多少

tip:

首先能想到一个点的前面+后面= n-1就是确定位置,那怎么知道呢?
dfs啊。。。。但是这个貌似是最短路专题QAQ,那就Floyd,floyd本身的想法就是用一个中间点更新两边点的关系,这个题也是一样,前驱的前驱一定是前驱,找到所有这样的就好啦

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 120;
int n,m,map[maxn][maxn];

void init(){
    memset(map,0,sizeof(map));
    for(int i = 0 ; i < m ; i++){
        int u,v;
        scanf("%d%d",&u,&v);
        map[u][v] = 1;
    }
}

void floyd(){
    for(int i = 1 ; i <= n ; i++)
        for(int j = 1; j <= n ; j++)
            for(int k = 1; k <= n ;k++)
                if(map[j][i] == 1 &&map[i][k] == 1)
                    map[j][k] = 1;
}

void sov(){
    int cnt = 0;
    for(int i = 1; i <= n ; i++){
        int ans = 0;
        for(int j = 1; j <= n ;j++){
            if(i==j)continue;
            if(map[i][j] == 1 || map[j][i] == 1)    ans++;
        }
        if(ans == n-1)  cnt++;
    }
    printf("%d\n",cnt);
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        init();
        floyd();
        sov();
    }
}

I题和之前一样。。。

#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;
#define MAXC 100
#define MAXV 50

double map[MAXV][MAXV];
int n,m;

void Input(){
    char s[MAXV][MAXC],a[MAXC],b[MAXC];
    int i,k,j;
    double c;
    for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            if(i==j)
                map[i][j]=1;
            else
                map[i][i]=0;
    for(i=1;i<=n;i++) scanf("%s",s[i]);
    scanf("%d\n",&m);
    for(i=1;i<=m;i++){
        scanf("%s %lf %s",a,&c,b);
        for(j=1;j<=n;j++)
            if(!strcmp(s[j],a)) break;
        for(k=1;k<=n;k++)
            if(!strcmp(s[k],b)) break;
        map[j][k]=c;
    }
}

void floyd(){
    int i,j,k;
    for(k=1;k<=n;k++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(map[i][k]*map[k][j]>map[i][j])
                    map[i][j]=map[i][k]*map[k][j];
}

int main(){
    int cas=1,i;
    while(scanf("%d\n",&n) && n){
        Input();
        floyd();
        printf("Case %d: ",cas++);
        for(i=1;i<=n;i++)
            if(map[i][i]>1) break;
        if(i>n) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}

J

反向图再来一次

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
#define MAXM 1000010
#define INF 0xFFFFFFFF

struct{
    int e,next,w;
}edge[2][MAXM];

__int64 d[MAXM],ans;
int n,m,headlist[2][MAXM],vis[MAXM];

void spfa(int cap){
    int v,i,b;
    queue <int>q;

    for(i=1;i<=n;i++){
        d[i]=INF;
        vis[i]=0;
    }

    q.push(1);
    vis[1]=1;
    d[1]=0;

    while(!q.empty()){
        v=q.front();
        q.pop();
        vis[v]=0;

        for(i=headlist[cap][v];i!=-1;i=edge[cap][i].next){
            b=edge[cap][i].e;
            if(d[b]>d[v]+edge[cap][i].w){
                d[b]=d[v]+edge[cap][i].w;
                if(!vis[b]){
                    vis[b]=1;
                    q.push(b);
                }
            }
        }
    }
}

int main(){
    int t,i,a,b,w;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            headlist[0][i]=-1;
            headlist[1][i]=-1;
        }

        for(i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&w);
            edge[0][i].w=w;
            edge[0][i].e=b;
            edge[0][i].next=headlist[0][a];
            headlist[0][a]=i;
            edge[1][i].w=w;
            edge[1][i].e=a;
            edge[1][i].next=headlist[1][b];
            headlist[1][b]=i;
        }
        ans=0;
        spfa(0);
        for(i=1;i<=n;i++) ans+=d[i];
        spfa(1);
        for(i=1;i<=n;i++) ans+=d[i];
        printf("%I64d\n",ans);
    }
    return 0;
}