标签:inf amp std += 操作 查找 有向环 最小 struct
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #define MAXN 1010 6 #define MAXM 1000000+10 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 struct Edge 10 { 11 int from; 12 int to; 13 double cost; 14 } e[MAXM]; 15 struct point 16 { 17 double x; 18 double y; 19 }p[MAXM]; 20 int pre[MAXN];//存储父节点 21 int vis[MAXN];//标记作用 22 int id[MAXN];//id[i]记录节点i所在环的编号 23 double in[MAXN];//in[i]记录i入边中最小的权值 24 double dis(point a,point b) 25 { 26 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 27 } 28 double zhuliu(int root, int n, int m)//root根 n点数 m边数 29 { 30 double res; 31 int u, v; 32 int i; 33 while(1) 34 { 35 for(i = 0; i < n; i++) 36 in[i] = INF;//初始化 37 for(i = 0; i < m; i++) 38 { 39 Edge E = e[i]; 40 if(E.from != E.to && E.cost < in[E.to]) 41 { 42 pre[E.to] = E.from;//记录前驱 43 in[E.to] = E.cost;//更新 44 } 45 } 46 for(i = 0; i < n; i++) 47 { 48 if(i != root && in[i] == INF)///除了根以外还有点没有入边,则不存在最小树形图 49 { 50 return -1; 51 } 52 } 53 //找有向环 54 int tn = 0;//记录当前查找中 环的总数 55 memset(id, -1, sizeof(id)); 56 memset(vis, -1, sizeof(vis)); 57 in[root] = 0;//根 58 for(i = 0; i < n; i++) 59 { 60 res += in[i];//累加 61 v = i; 62 //找图中的有向环 三种情况会终止while循环 63 //1,直到出现带有同样标记的点说明成环 64 //2,节点已经属于其他环 65 //3,遍历到根 66 while(vis[v] != i && id[v] == -1 && v != root) 67 { 68 vis[v] = i;//标记 69 v = pre[v];//一直向上找 70 } 71 //因为找到某节点属于其他环 或者 遍历到根 说明当前没有找到有向环 72 if(v != root && id[v] == -1)//必须上述查找已经找到有向环 73 { 74 for(int u = pre[v]; u != v; u = pre[u]) 75 { 76 id[u] = tn;//记录节点所属的 环编号 77 } 78 id[v] = tn++;//记录节点所属的 环编号 环编号累加 79 } 80 } 81 if(tn == 0) 82 { 83 break;///不存在有向环 84 } 85 for(i = 0; i < n; i++) //可能存在独立点 86 { 87 if(id[i] == -1) 88 { 89 id[i] = tn++;//环数累加 90 } 91 } 92 for(i = 0; i < m; i++)///缩点,重新标记 93 { 94 v = e[i].to; 95 e[i].from = id[e[i].from]; 96 e[i].to = id[e[i].to]; 97 //<u, v>有向边 98 //两点不在同一个环 u到v的距离为 边权cost - in[v] 99 if(e[i].from != e[i].to) 100 { 101 e[i].cost -= in[v];//更新边权值 继续下一条边的判定 102 } 103 } 104 n = tn;///以环总数为下次操作的点数 继续执行上述操作 直到没有环 105 root = id[root]; 106 } 107 return res; 108 } 109 int main() 110 { 111 int n,m; 112 while(scanf("%d%d",&n,&m)!=EOF) 113 { 114 int i; 115 double ans; 116 for(i=0; i<n; i++) 117 { 118 scanf("%lf%lf",&p[i].x,&p[i].y); 119 } 120 for(i=0; i<m; i++) 121 { 122 scanf("%d%d",&e[i].from,&e[i].to); 123 e[i].from--; 124 e[i].to--; 125 if(e[i].from!=e[i].to) 126 { 127 e[i].cost=dis(p[e[i].from],p[e[i].to]); 128 } 129 else 130 { 131 e[i].cost=INF; 132 } 133 } 134 ans=zhuliu(0,n,m); 135 if(ans==-1) 136 { 137 printf("poor snoopy\n"); 138 } 139 else 140 { 141 printf("%.2f\n",ans); 142 } 143 } 144 return 0; 145 }
标签:inf amp std += 操作 查找 有向环 最小 struct
原文地址:https://www.cnblogs.com/wkfvawl/p/9447929.html