题意:卡了一天的一题。有若干个小球当中连着一些绳子(绳子一样长)现在需要你选两个小球, 需要当你尽量分开这些小球的时候绷紧的绳子数最多。
思路:其实就是求两点之间所有最短路的边最多的值,首先要用floyd找出所有节点之间的最短路,然后在用搜索找到任意两个节点之间的最短路覆盖多少条边。我是开了一个矩阵标记边有没有被访问过,若是能到达目标状态(最短路)则再回溯的事后标记边。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #define LEN 130 10 #define INF 0x3f3f3f3f 11 12 using namespace std; 13 14 int dis[LEN][LEN], n, m, Map[LEN][LEN], kase = 1; 15 bool vis[LEN], ve[LEN][LEN]; 16 17 void floyd() 18 { 19 for(int i=0; i<n; i++){ 20 for(int j=0; j<n; j++){ 21 if(i!=j)dis[i][j] = Map[i][j]; 22 else dis[i][j] = 0; 23 } 24 } 25 for(int k=0; k<n; k++){ 26 for(int i=0; i<n; i++){ 27 for(int j=0; j<n; j++){ 28 if(dis[k][j]!=INF && dis[i][k]!=INF && dis[i][j]>dis[i][k]+dis[k][j]){ 29 dis[i][j] = dis[i][k]+dis[k][j]; 30 } 31 } 32 } 33 } 34 } 35 36 int DFS(int pos, int s, int e, int st) 37 { 38 if(st==dis[s][e]){ 39 if(pos==e){ 40 return 0; 41 } 42 return -1; 43 } 44 int ret = 0, f = 1; 45 for(int i=0; i<n; i++){ 46 if(i!=pos && Map[pos][i]==1 && !vis[i]){ 47 vis[i] = true; 48 int temp=DFS(i, s, e, st+1); 49 vis[i] = false; 50 if(temp!=-1){ 51 f = 0; 52 ret += temp; 53 if(!ve[pos][i]){ 54 ve[pos][i] = ve[i][pos] = true; 55 ret ++; 56 } 57 } 58 } 59 } 60 ret-=f; 61 return ret; 62 } 63 64 int main() 65 { 66 // freopen("in.txt", "r", stdin); 67 68 int T, a, b; 69 scanf("%d", &T); 70 while(T--){ 71 scanf("%d%d", &n, &m); 72 memset(Map, 0x3f, sizeof Map); 73 for(int i=0; i<m; i++){ 74 scanf("%d%d", &a, &b); 75 Map[a][b] = Map[b][a] = 1; 76 } 77 floyd(); 78 int ans = 0; 79 for(int i=0; i<n; i++){ 80 for(int j=0; j<i; j++){ 81 memset(vis, 0, sizeof vis); 82 memset(ve, 0, sizeof ve); 83 vis[i] = true; 84 ans = max(ans, DFS(i,i,j,0)); 85 } 86 } 87 printf("Case #%d: %d ", kase++, ans); 88 } 89 return 0; 90 }