HDU 6166 Senior Pan
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6166
题意:
给一张n个点m条边的有向图(1≤n,m≤100000),然后给一大波点设为集合V,问V内两点的最短距离。
题解:
看到这题的时候想设一个超级源点,连上V内的点,一个超级汇点连上V内的点且距离都为0,也就是求超级源点和汇点的最短路了,然后又一想如果源点连的点和汇点连的点一样不就GG了吗。
然后就是解决这个问题,我们能不能做下标记使其源点连的点和汇点连的不一样,那么维护一个from就可以了,怎么维护呢,其实就是次短路,考虑源点出去两条最短的路线(其实就是最短路和次短路)到经过某一点到终点所连的点,如果这其中某一条路径和终点连的点重合了,那么就用另外一个点作为源点所连的点就行了,那么对于V里的任一点u也一样,源点到这些点的最短路径其实就是0,from是u本身,如果有一条源点不是u的最短路就行了,不就是次短路吗?比赛的时候900+ms水过。。
比赛完了信心满满的去看题解然后说是类似于CF的835E,通过什么玄学的东西搞的(没仔细看,水过就行了),那种方法的复杂度是20*dijkstra,好久没打过CF了。。。。。
比赛时候在队友电脑上写的代码变量命名,文件啥的有点乱。。。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const long long INF=1e18; 5 const int maxn=100000+10; 6 typedef long long ll; 7 typedef pair<ll, ll> pii; 8 int T,u,v,w,n,m,k,cc; 9 bool vis[maxn]; 10 struct node { 11 int v,w; 12 node() {} 13 node(int a, int b) {v=a;w=b;} 14 }; 15 struct tnode { 16 int v;long long d; int f; 17 tnode(){} 18 tnode(int a,long long b,int c){v=a;d=b;f=c;} 19 bool operator < (const tnode& a) const { 20 return d>a.d; 21 } 22 }; 23 int from[maxn][2]; 24 long long d[maxn][2]; 25 vector<node> g[maxn]; 26 void dik () { 27 priority_queue<tnode>que; 28 for(int i=1;i<=n;++i){ 29 if(vis[i]) { 30 que.push(tnode(i,0,i)); 31 } 32 } 33 while(!que.empty()) { 34 tnode p=que.top();que.pop(); 35 int v=p.v; long long ds=p.d; 36 if(d[v][1]<ds)continue; 37 for(auto x:g[v]) { 38 long long d2=ds+x.w; int tfs=p.f; 39 if(d[x.v][0]>d2) { 40 swap(d[x.v][0],d2); 41 swap(tfs,from[x.v][0]); 42 que.push(tnode(x.v,d[x.v][0],from[x.v][0])); 43 } 44 if(d[x.v][1]>d2&&tfs!=from[x.v][0]) { 45 d[x.v][1]=d2; 46 from[x.v][1]=tfs; 47 que.push(tnode(x.v,d[x.v][1],from[x.v][1])); 48 } 49 50 } 51 } 52 } 53 int main() { 54 #ifdef __AiR_H 55 freopen("1001.in", "r", stdin); 56 #endif // __AiR_H 57 scanf("%d",&T); 58 while(T--) { 59 scanf("%d%d",&n,&m); 60 for(int i=1;i<=n;++i) { 61 g[i].clear(); 62 } 63 for(int i=1;i<=m;++i) { 64 scanf("%d%d%d",&u,&v,&w); 65 g[u].push_back(node{v,w}); 66 } 67 68 memset(vis,0,sizeof(vis)); 69 scanf("%d",&k); 70 for(int i=1;i<=k;++i) { 71 scanf("%d",&u); vis[u]=1; 72 } 73 for(int i=1;i<=n;++i) { 74 if(!vis[i]) { 75 from[i][0]=0; 76 from[i][1]=0; 77 d[i][1]=INF; 78 d[i][0]=INF; 79 } 80 else { 81 from[i][0]=i; 82 from[i][1]=0; 83 d[i][0]=0; 84 d[i][1]=INF; 85 } 86 } 87 dik(); 88 long long ans=INF; 89 for(int i=1;i<=n;++i) { 90 if(vis[i]) { 91 92 ans=min(ans,d[i][1]); 93 } 94 } 95 printf("Case #%d: %lld\n",++cc,ans); 96 } 97 return 0; 98 }
沉迷于日日菜醒,不能自拔
posted on 2017-08-22 19:25 仰望咸鱼Orzzzz 阅读(292) 评论(0) 编辑 收藏 举报