题目链接: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 ",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 ",dis[n]); else printf("%d ",Max+1); } } return 0; }