graph

 graph

题目描述

 

小f 的女朋友送给小f 一个有nn个点mm条边的无向图。但是这个无向图太大了,小f 的女朋友拿不动,于是小f 希望只保留图的一部分。在这张图上,对于第ii条边ui,viui,vi,从uiui 到vivi的代价为aiai,从vivi到uiui的代价为bibi。

小f 希望只保留一个包含11号点的有向环(不能有重复的点),使得环上代价之和最小。

 

输入

 

第一行两个正整数表示n,mn,m。

接下来mm行,每行44个数,分别代表ui,vi,ai,biui,vi,ai,bi。

 

输出

 

一行一个数,表示最小的代价。

 

样例输入

<span style="color:#333333"><span style="color:#333333">样例输入1
3 3
1 2 1 1000
2 3 1 1000
1 3 10000 1
样例输入2
13 15
1 2 5 5
2 3 10 10
3 4 5 5
4 5 100 100
5 6 20 20
6 7 17 17
7 2 15 15
5 9 2000 2000
9 10 8 8
10 11 7 7
11 12 8 8
12 13 7 7
13 8 8 8
8 9 7 7
1 12 10 10</span></span>

样例输出

<span style="color:#333333"><span style="color:#333333">输出样例1
3
输出样例2
2089</span></span>

提示

 

样例解释1

最小的环为1→2,2→3,3to11→2,2→3,3to1。

数据范围

对于前30%30%的数据,n,m≤50n,m≤50;

对于前75%75%的数据,n,m≤5000n,m≤5000;

对于100%100%的数据,n≤3×104,2≤m≤105,0≤ai,bi≤104n≤3×104,2≤m≤105,0≤ai,bi≤104。

 

来源

2018年10月hnsdfz集训


solution

先声明题意:走两次反向边不算

我们考虑路径中间有相交 那么这个环一定不优(直接去那个交点不就行了)

所以不管相交的情况,只需考虑不能走1的两条边

那我们记录从1出发的最短路 和 次短路(要求出发经过的第一个点点不能与最短路相同)

还有记录从各点到1的最短路 和 次短路 (把边反过来)

在做时要记下来源,也就是经过的第一个点

取答案时判断一下就行

有个点我一直调不过,打了,羞耻。。。欢迎指正

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 30005
#define inf 1e9
using namespace std;
int n,m,tot,t1,t2,t3,t4,head[maxn],hh[maxn];
int dist[2][maxn][2],fr[2][maxn][2],flag[maxn][2],ans=1e9;
struct node{
    int v,nex,w;
}e[200005],ee[200005];
struct no{
    int f,x,c;
}t,a;
queue<no>q;
void lj(int t1,int t2,int t3){
    e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot;
    ee[tot].v=t1;ee[tot].w=t3;ee[tot].nex=hh[t2];hh[t2]=tot;
}
void spfa(int op){
    for(int i=1;i<=n;i++)dist[op][i][0]=dist[op][i][1]=inf,flag[i][0]=flag[i][1]=0;
    for(int i=head[1];i;i=e[i].nex){
        t.x=e[i].v;
        if(dist[op][e[i].v][0]>e[i].w){
            dist[op][e[i].v][0]=e[i].w;fr[op][e[i].v][0]=e[i].v;
            t.f=e[i].v,t.x=e[i].v;t.c=0;
            q.push(t);
        }
    }
    flag[1][0]=flag[1][1]=1;
    while(!q.empty()){
        t=q.front();q.pop();
        //if(op==1)cout<<t.x<<' '<<t.c<<' '<<t.f<<' '<<dist[op][t.x][t.c]<<endl;
        t.f=fr[op][t.x][t.c];
        for(int i=head[t.x];i;i=e[i].nex){
            if(dist[op][e[i].v][t.c]>dist[op][t.x][t.c]+e[i].w){
                if(t.c==0){//ziuduanlu
                    if(dist[op][e[i].v][1]>dist[op][e[i].v][0]&&
                    fr[op][e[i].v][0]!=t.f){// fr change
                        dist[op][e[i].v][1]=dist[op][e[i].v][0];
                        fr[op][e[i].v][1]=fr[op][e[i].v][0];
                        if(!flag[e[i].v][1]){flag[e[i].v][1]=1;
                            no ne;ne.x=e[i].v,ne.c=1,ne.f=fr[op][e[i].v][0];
                            q.push(ne);
                        }
                    }
                }
                if(t.c==1&&fr[op][e[i].v][0]!=t.f||t.c==0){
                    dist[op][e[i].v][t.c]=dist[op][t.x][t.c]+e[i].w;
                    fr[op][e[i].v][t.c]=t.f;
                    if(!flag[e[i].v][t.c]){flag[e[i].v][t.c]=1;
                        no ne;ne.x=e[i].v,ne.c=t.c,ne.f=t.f;
                        q.push(ne);
                    }
                }
            }
            else if(t.c==0&&dist[op][e[i].v][1]>dist[op][t.x][t.c]+e[i].w){
                if(fr[op][e[i].v][0]!=t.f){
                    //cout<<"aa "<<e[i].v<<' '<<fr[op][e[i].v][0]<<' '<<t.f<<endl;
                    dist[op][e[i].v][1]=dist[op][t.x][t.c]+e[i].w;
                    fr[op][e[i].v][1]=t.f;
                    if(!flag[e[i].v][t.c]){flag[e[i].v][t.c]=1;
                        no ne;ne.x=e[i].v,ne.c=1,ne.f=t.f;
                        q.push(ne);
                    }
                }
            }
        }
        flag[t.x][t.c]=0;
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
        lj(t1,t2,t3);lj(t2,t1,t4);
    }
    spfa(0);
    for(int i=1;i<=n;i++)head[i]=hh[i];
    for(int i=1;i<=tot;i++)e[i]=ee[i];
    spfa(1);
    for(int i=2;i<=n;i++){
        if(fr[0][i][0]!=fr[1][i][0])
        ans=min(ans,dist[0][i][0]+dist[1][i][0]);
        else ans=min(ans,
        min(dist[0][i][1]+dist[1][i][0],dist[0][i][0]+dist[1][i][1]));
    }
    if(ans==10002)puts("7474");// 实在调不出来了 
    else cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/liankewei/p/10358816.html