Cow and Fields

题目链接:http://codeforces.com/contest/1307/problem/D

题意:有n个点,m条边,n个点里有k个特殊的点,现在你要在两个特殊的点之间加一条边(不管之前是否有边),加完边后要让1号点到n号点的最短路径及可能的长

思路:我们可以先求出所有特殊的点到点1和点x的距离,特殊点i到点1的距离为xi ,到点n的距离为yi。然后选择两个字段 aaa 和 bbb 来最大化min(xa+yb,ya+xb)。

         然后再按xi-yi从小到大排序就可以了。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const int Inf=999999999;
int n,m,k;
struct node
{
    int v,w;//后继结点与权值
    node() {}
    node(int vv,int ww)
    {
        v=vv;
        w=ww;
    }
};
struct Node
{
    int u,w;//前驱结点与权值
    Node() {}
    Node(int uu,int ww)
    {
        u=uu;
        w=ww;
    }
    bool operator<(const Node other)const
    {
        return w>other.w;
    }
};
struct nd
{
    int l,r,v;
} aa[200005];
bool cmp(nd a,nd b)
{
    return a.v<b.v;
}
const int N=200005;
int book[N],dis[N],vv[N],bookk[N],dis1[N],mm[N],cc[N];
vector<node> G[N];
void Dijkstra()
{
    priority_queue<Node> p;
    memset(book,0,sizeof(book));
    for(int i=1; i<=n; i++)
        dis[i]=Inf;
    dis[1]=0;
    p.push(Node(1,dis[1]));
    while(!p.empty())
    {
        Node temp=p.top();
        p.pop();
        int u=temp.u;
        if(book[u])
            continue;
        book[u]=1;
        for(int i=0; i<G[u].size(); i++)
        {
            node tv=G[u][i];
            int v=tv.v;
            int w=tv.w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                p.push(Node(v,dis[v]));
            }
        }
    }
}
void Dijkstra1()
{
    priority_queue<Node> p;
    memset(bookk,0,sizeof(bookk));
    for(int i=1; i<=n; i++)
        dis1[i]=Inf;
    dis1[n]=0;
    p.push(Node(n,dis1[n]));
    while(!p.empty())
    {
        Node temp=p.top();
        p.pop();
        int u=temp.u;
        if(bookk[u])
            continue;
        bookk[u]=1;
        for(int i=0; i<G[u].size(); i++)
        {
            node tv=G[u][i];
            int v=tv.v;
            int w=tv.w;
            if(dis1[v]>dis1[u]+w)
            {
                dis1[v]=dis1[u]+w;
                p.push(Node(v,dis1[v]));
            }
        }
    }
}
int main()
{

    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=1; i<=k; i++)
        {

            scanf("%d",&mm[i]);
            vv[mm[i]]=1;
        }
        int u,v,w;
        bool ff=0;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            if(vv[u]&&vv[v])
                ff=1;
            G[u].push_back(node(v,1));
            G[v].push_back(node(u,1));
        }
        Dijkstra();
        Dijkstra1();
        if(ff)
            printf("%d\n",dis[n]);
        else
        {
            int cnt=0;
            for(int i=1; i<=k; i++)
            {
                aa[++cnt].l=dis[mm[i]];
                aa[cnt].r=dis1[mm[i]];
                aa[cnt].v=aa[cnt].l-aa[cnt].r;
            }
            sort(aa+1,aa+k+1,cmp);
            int Max=0;
            for(int i=k; i>=1; i--)
            {
                cc[i]=max(aa[i].r,Max);
            }
            Max=0;
            for(int i=1; i<k; i++)
            {
                Max=max(Max,aa[i].l+cc[i+1]);
            }
            if(Max+1>dis[n])
                printf("%d\n",dis[n]);
            else
                printf("%d\n",Max+1);
        }
    }
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/zcb123456789/p/12329140.html
今日推荐