标签:拓扑序 can 直接 过程 stdio.h one def while span
n<=25000个点m1<=50000条正权无向边m2<=50000条正负权有向边,保证有向边连接的无向边联通块形成一个拓扑图,求从s到每个点最短路。
第一次发现不会最短路。没看题乱写迪杰无脑WA,很好。迪杰从来不能处理负权最短路,然后就开始啃题解。。http://www.cnblogs.com/staginner/archive/2012/10/01/2709487.html这篇代码不错,讲得也很好。
在每个无向边联通块中找最短路可以直接迪杰。至于过度到不同的联通块,可以对无向图联通块形成的拓扑图按拓扑序来走。也就是说开一个队列记待搜集和每个集合在从前搜到的起点,在每次迪杰时利用并更新他们。
过程有点长,需组织完整后一气呵成!
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 #include<queue> 7 using namespace std; 8 9 int n,m1,m2,s; 10 #define maxn 25011 11 #define maxm 100011 12 const int inf=0x3f3f3f3f; 13 struct Edge{int to,next,v;}; 14 struct qnode 15 { 16 int v,id; 17 bool operator < (const qnode &b) const {return v<b.v;} 18 bool operator > (const qnode &b) const {return v>b.v;} 19 }; 20 int ufs[maxn]; 21 void ufsclear(int n) 22 { 23 for (int i=1;i<=n;i++) ufs[i]=i; 24 } 25 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));} 26 void Union(int x,int y) 27 { 28 x=find(x),y=find(y); 29 if (x==y) return; 30 ufs[x]=y; 31 } 32 struct Graph 33 { 34 Edge road[maxm],fly[maxm]; 35 int froad[maxn],ffly[maxn],lr,lf; 36 Graph() 37 { 38 memset(froad,0,sizeof(froad)); 39 memset(ffly,0,sizeof(ffly)); 40 lr=lf=2; 41 } 42 void in(Edge *edge,int *first,int &le,int x,int y,int v) 43 { 44 Edge &e=edge[le]; 45 e.to=y;e.v=v; 46 e.next=first[x]; 47 first[x]=le++; 48 } 49 void insert(Edge *edge,int *first,int &le,int x,int y,int v) 50 { 51 in(edge,first,le,x,y,v); 52 in(edge,first,le,y,x,v); 53 } 54 void in(int x,int y,int v) {in(fly,ffly,lf,x,y,v);} 55 void insert(int x,int y,int v) {insert(road,froad,lr,x,y,v);} 56 int deg[maxn]; 57 int que[maxn],head,tail;bool vis[maxn]; 58 void bfs() 59 { 60 que[head=(tail=1)-1]=s; 61 vis[s]=1; 62 memset(deg,0,sizeof(deg)); 63 while (head!=tail) 64 { 65 const int now=que[head++]; 66 for (int i=froad[now];i;i=road[i].next) 67 { 68 Edge &e=road[i]; 69 if (!vis[e.to]) vis[e.to]=1,que[tail++]=e.to; 70 } 71 for (int i=ffly[now];i;i=fly[i].next) 72 { 73 Edge &e=fly[i]; 74 deg[find(e.to)]++; 75 if (!vis[e.to]) vis[e.to]=1,que[tail++]=e.to; 76 } 77 } 78 } 79 Edge play[maxn]; 80 int fplay[maxn],lp; 81 int dis[maxn]; 82 void inplay(int x,int y) 83 { 84 play[lp].to=y; 85 play[lp].next=fplay[x]; 86 fplay[x]=lp++; 87 } 88 void dijkstra(int x) 89 { 90 priority_queue<qnode,vector<qnode>,greater<qnode> > q; 91 for (int i=fplay[x];i;i=play[i].next) 92 { 93 Edge &e=play[i]; 94 q.push((qnode){dis[e.to],e.to}); 95 vis[e.to]=0; 96 } 97 while (!q.empty()) 98 { 99 const int now=q.top().id,d=q.top().v;q.pop(); 100 if (vis[now]) continue; 101 vis[now]=1; 102 for (int i=froad[now];i;i=road[i].next) 103 { 104 Edge &e=road[i]; 105 if (dis[e.to]>d+e.v) 106 { 107 dis[e.to]=d+e.v; 108 q.push((qnode){dis[e.to],e.to}); 109 } 110 } 111 for (int i=ffly[now];i;i=fly[i].next) 112 { 113 Edge &e=fly[i]; 114 if (dis[e.to]>d+e.v) 115 { 116 dis[e.to]=d+e.v; 117 if (!vis[e.to]) 118 { 119 vis[e.to]=1; 120 inplay(find(e.to),e.to); 121 } 122 } 123 deg[find(e.to)]--; 124 if (!deg[ufs[e.to]]) que[tail++]=ufs[e.to]; 125 } 126 } 127 } 128 void solve() 129 { 130 bfs(); 131 for (int i=1;i<=n;i++) dis[i]=inf;dis[s]=0; 132 memset(fplay,0,sizeof(fplay));lp=2; 133 que[head=(tail=1)-1]=find(s); 134 inplay(ufs[s],s); 135 memset(vis,0,sizeof(vis)); 136 while (head!=tail) 137 { 138 const int now=que[head++]; 139 dijkstra(now); 140 } 141 for (int i=1;i<=n;i++) 142 printf(dis[i]==inf?"NO PATH\n":"%d\n",dis[i]); 143 } 144 }g; 145 int x,y,v; 146 int main() 147 { 148 scanf("%d%d%d%d",&n,&m1,&m2,&s); 149 ufsclear(n); 150 for (int i=1;i<=m1;i++) 151 { 152 scanf("%d%d%d",&x,&y,&v); 153 g.insert(x,y,v); 154 Union(x,y); 155 } 156 for (int i=1;i<=m2;i++) 157 { 158 scanf("%d%d%d",&x,&y,&v); 159 g.in(x,y,v); 160 } 161 g.solve(); 162 return 0; 163 }
BZOJ2200: [Usaco2011 Jan]道路和航线
标签:拓扑序 can 直接 过程 stdio.h one def while span
原文地址:http://www.cnblogs.com/Blue233333/p/7450516.html