给我们一张图,问我们摧毁边使得s和t不连通有多少种方案, 方案与方案之间不能存在相同的摧毁目标。
这是一个神奇的题目。
这题可以转为求s与t的最短路,为什么呢?
因为方案与方案之间不能存在相同的催婚目标。
那么最短路上的边肯定要被摧毁,才能使得s和t不连通。
那么只要一个方案摧毁最短路上的一条边,外加一些最短路外的边, 那么就会使得方案数最多。方案数为最短路的长度。
那么问题来了,我们摧毁的最短路上的边是不会相同的,但是最短路外的边呢?会不会相同呢?
我们假设最短路是s -- x1 -- x2 -- x3 -- x4--...---t
我们删除最短路的第一条边 s--x1, 然互再删除以s开头的边,那么使得s与最短路分离, 即图不连通
我们删除最短路的第二条边 x1--x2, 然后删除以x1开头,且不与s直连的边,使得图不连通
以此类推。 摧毁最短路之外的边是不会相同的。
所以,我们求个s->t的最短路就行了
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1<<30; 17 /* 18 19 */ 20 struct Edge 21 { 22 int to,dist; 23 bool operator<(const Edge&rhs)const 24 { 25 return dist > rhs.dist; 26 } 27 }; 28 vector<Edge> g[10000+10]; 29 int dist[10000+10]; 30 bool vis[10000+10]; 31 void dij(int s) 32 { 33 priority_queue<Edge> q; 34 Edge cur,tmp; 35 cur.dist = 0; 36 cur.to = s; 37 q.push(cur); 38 dist[s] = 0; 39 while(!q.empty()) 40 { 41 cur = q.top(); q.pop(); 42 int u = cur.to; 43 if(vis[u]) continue; 44 vis[u] = true; 45 for(int i=0; i<g[u].size(); ++i) 46 { 47 int v = g[u][i].to; 48 if(dist[v] > dist[u] + g[u][i].dist) 49 { 50 tmp.dist = dist[v] = dist[u] + g[u][i].dist; 51 tmp.to = v; 52 q.push(tmp); 53 } 54 } 55 } 56 57 } 58 int main() 59 { 60 int n,m,s,t,i,a,b; 61 Edge tmp; 62 while(true) 63 { 64 scanf("%d%d%d%d",&n,&m,&s,&t); 65 if(n==0) 66 break; 67 for(i=1; i<=n; ++i) 68 { 69 g[i].clear(); 70 vis[i] = false; 71 dist[i] = INF; 72 } 73 for(i=0; i<m; ++i) 74 { 75 scanf("%d%d",&a,&b); 76 tmp.to = b; 77 tmp.dist = 1; 78 g[a].push_back(tmp); 79 tmp.to = a; 80 g[b].push_back(tmp); 81 } 82 dij(s); 83 printf("%d\n",dist[t]); 84 } 85 return 0; 86 }
时间: 2024-10-14 08:17:46