ACdream1415--最短路,桥

本文介绍了一种算法,用于找出从起点到终点的路径中哪些路径被认为是关键路径,即一旦这些路径被移除,从起点到终点的最短路径将受到影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C - Important Roads
Time Limit:2000MS     Memory Limit:64000KB     64bit IO Format:%lld & %llu

Description

      The city where Georgie lives has n junctions some of which are connected by bidirectional roads.
      Every day Georgie drives from his home to work and back. But the roads in the city where Georgie lives are very bad, so they are very often closed for repair. Georgie noticed that when some roads are closed he still can get from home to work in the same time as if all roads were available.

      But there are such roads that if they are closed for repair the time Georgie needs to get from home to work increases, and sometimes Georgie even cannot get to work by a car any more. Georgie calls such roads important.
      Help Georgie to find all important roads in the city.

Input

      The first line of the input file contains n and m — the number of junctions and roads in the city where Georgie lives, respectively (2 ≤ n ≤ 20 000, 1 ≤ m ≤ 100 000). Georgie lives at the junction 1 and works at the junction n.

      The following m lines contain information about roads. Each road is specified by the junctions it connects and the time Georgie needs to drive along it. The time to drive along the road is positive and doesn’t exceed 100 000. There can be several roads between a pair of junctions, but no road connects a junction to itself. It is guaranteed that if all roads are available, Georgie can get from home to work.

Output

      Output l — the number of important roads — at the first line of the output file. The second line must contain l numbers, the numbers of important roads. Roads are numbered from 1 to m as they are given in the input file.

Sample Input

6 7
1 2 1
2 3 1
2 5 3
1 3 2
3 5 1
2 4 1
5 6 2

Sample Output

2

5 7

题意:某人在一个城市上班,由于道路条件不好,经常会修路,这样他就得换路走,走每条路花费时间不同,他的家在1点,公司在n点,保证在不修路情况下,他可以正常时间到达公司,如果修某条路后,他不能按时到达公司称这条路为关键路径,即我们所说的桥,问这样的路有几条,并把路编号按顺序输出;

首先要把1-n的最短路径求出,最短路径就是最短时间,即他按时到达公司,然后在这个最短路径上找桥并输出

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL inf=0x3f3f3f3f;
const int maxn=20010,maxm=100050;
int N;
struct edge
{
    int v,cost,id;
    int next;
} e1[maxm*2],e2[maxm*2];
int head1[maxn],head2[maxn];
int tot1,tot2,cnt;
void addedge(int u,int v,int w,int i)
{
    e1[tot1].id=i;
    e1[tot1].v=v;
    e1[tot1].cost=w;
    e1[tot1].next=head1[u];
    head1[u]=tot1++;
}
bool vis[maxn+10];
int dist1[maxn],dist2[maxn];
struct node
{
    int vex,road;
    node (){;}
    node(int v,int r)
    {
        vex=v;
        road=r;
    }
    friend bool operator < (const node a,const node b )
    {
        return a.road>b.road;
    }
};
void dj1(int s)
{
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=N; i++)
        dist1[i]=inf;
    priority_queue<node>que;
    dist1[s]=0;
    que.push(node(s,0));
    while(!que.empty())
    {
        node n1=que.top();
        que.pop();
        int u=n1.vex;
        if(dist1[u]<n1.road)
            continue;
        for(int i=head1[u];i!=-1;i=e1[i].next)
        {
            int v=e1[i].v;
            if(dist1[v]>dist1[u]+e1[i].cost)
            {
                dist1[v]=dist1[u]+e1[i].cost;
                que.push(node(v,dist1[v]));
            }
        }
    }
}
void dj2(int s)
{
    memset(vis,false,sizeof(vis));
    for(int i=1; i<=N; i++)
        dist2[i]=inf;
    priority_queue<node>que;
    dist2[s]=0;
    que.push(node(s,0));
    while(!que.empty())
    {
        node n1=que.top();
        que.pop();
        int u=n1.vex;
        if(dist2[u]<n1.road)
            continue;
        for(int i=head1[u];i!=-1;i=e1[i].next)
        {
            int v=e1[i].v;
            if(dist2[v]>dist2[u]+e1[i].cost)
            {
                dist2[v]=dist2[u]+e1[i].cost;
                que.push(node(v,dist2[v]));
            }
        }
    }
}
void add(int u,int v,int id)
{
     e2[tot2].v=v;
     e2[tot2].id=id;
     e2[tot2].next=head2[u];
     head2[u]=tot2++;
}
void build()
{
    tot2=0;
    memset(head2,-1,sizeof(head2));
    for(int u=1; u<=N; u++)
    {
        for(int i=head1[u]; i!=-1; i=e1[i].next)
        {
            int v=e1[i].v;
            if((dist1[u]+dist2[v]+e1[i].cost)==dist1[N])
            {
                add(u,v,e1[i].id);
                add(v,u,e1[i].id);
            }
        }
    }
}
int ans[maxn];
int cnt2;
int Low[maxn],DFN[maxn];
int Index,top;
///求桥
void tarjan(int u,int pre)
{
    int pre_num=0;
    DFN[u]=Low[u]=++cnt;
    for(int i=head2[u]; i!=-1; i=e2[i].next)
    {
        int v=e2[i].v;
        if(v==pre&&pre_num==0)
        {
            pre_num++;
            continue;
        }
        if(!DFN[v])
        {

            tarjan(v,u);
            Low[u]=min(Low[u],Low[v]);
            if(Low[v]>DFN[u])
            {
                ans[cnt2++]=e2[i].id;
            }
        }
        else if(Low[u]>DFN[v])
        {
            Low[u]=DFN[v];
        }
    }
}
void solve(int n)
{
    memset(DFN,0,sizeof(DFN));
    Index=top=0;
    cnt2=0;
    for(int i=1; i<=n; i++)
    {
        if(!DFN[i])
          tarjan(i,i);
    }
    sort(ans,ans+cnt2);
    printf("%d\n",cnt2);
    if(cnt2)
    {
        for(int i=0;i<cnt2-1;i++)
        printf("%d ",ans[i]);
       printf("%d\n",ans[cnt2-1]);
    }
}
int main()
{
    int u,v,w;
    int m,n;
    while(~scanf("%d%d",&n,&m))
    {
        N=n;
        memset(head1,-1,sizeof(head1));
        tot1=0;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w,i);
            addedge(v,u,w,i);
        }
        dj1(1);///求1到其他点最短路
        dj2(n);///求n到其他店最短路
        build();///构建新图,1-n的可到路径,且是最短路上的边
        solve(n);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值