Codeforces 240E Road Repairs(最小树形图路径)
2016-05-21 00:03
162 查看
题目链接:
Codeforces 240E Road Repairs
题意:
有n个城市,编号1–n,首都编号为1,有m条有向边u[i],v[i],w[i],w[i]=0表示这条边是完好的,w[i]=1表示这条边需要修理,问从首都出发能到达任意城市最少需要修多少条边?如果不能到达任意城市输出-1,否则输出需要修复的最少边数和边的编号。如果有多组答案输出任意一组。
分析:
输出最小树形图的路径。
Codeforces 240E Road Repairs
题意:
有n个城市,编号1–n,首都编号为1,有m条有向边u[i],v[i],w[i],w[i]=0表示这条边是完好的,w[i]=1表示这条边需要修理,问从首都出发能到达任意城市最少需要修多少条边?如果不能到达任意城市输出-1,否则输出需要修复的最少边数和边的编号。如果有多组答案输出任意一组。
分析:
输出最小树形图的路径。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <climits> #include <cmath> #include <ctime> #include <cassert> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; const int MAX_N = 100010; const int MAX_M = 2000010; const int INF = 0x7fffffff; int n, m, NV, NE; int pre[MAX_N], vis[MAX_N], In[MAX_N], ID[MAX_N]; int usedEdge[MAX_M], preEdge[MAX_N]; struct Edge{ int u, v, w, ww, id; Edge() {} Edge(int _u, int _v, int _w, int _ww, int _id) : u(_u), v(_v), w(_w), ww(_ww), id(_id) {} }edge[MAX_M]; struct Used{ int pre, id; }cancle[MAX_M]; int ZLEdmonds(int root) { memset(usedEdge, 0, sizeof(usedEdge)); int res = 0, u, v, w; int total = NE; while(1){ for(int i = 0; i < NV; i++) { In[i] = INF; } for(int i = 0; i < NE; i++){ u = edge[i].u, v = edge[i].v, w = edge[i].w; if(u != v && w < In[v]){ In[v] = w; pre[v] = u; //记录这个顶点所在的边编号 preEdge[v] = edge[i].id; } } for(int i = 0; i < NV; i++){ if(i != root && In[i] == INF) return -1; } int cnt = 0; memset(vis, -1, sizeof(vis)); memset(ID, -1, sizeof(ID)); In[root] = 0; for(int i = 0; i < NV; i++){ res += In[i]; v = i; if(i != root){ //非根节点 usedEdge[preEdge[i]]++; //这个顶点所在的边被使用 int t = preEdge[i]; } while(v != root && vis[v] != i && ID[v] == -1){ vis[v] = i; v = pre[v]; } if(v != root && ID[v] == -1){ for(u = pre[v]; u != v; u = pre[u]){ ID[u] = cnt; } ID[v] = cnt++; } } if(cnt == 0) break; for(int i = 0; i < NV; i++){ if(ID[i] == -1) ID[i] = cnt++; } for(int i = 0; i < NE;i ++){ u = edge[i].u, v = edge[i].v; edge[i].u = ID[u], edge[i].v = ID[v]; //将原先的边的id重新编号 if(edge[i].u != edge[i].v){ //edge[i].u 和edge[i].v 是新图的点编号,两者不相等说明两者在原图中不属于同一有向环 edge[i].w -= In[v]; //如果在新图中用到该边那么上一次图中用到这条边就要被取消 cancle[total].id = edge[i].id; cancle[total].pre = preEdge[v]; //重新编排新图的边的编号 edge[i].id = total++; } } NV = cnt; root = ID[root]; } for(int i = total - 1; i >= NE; i--){ //从后往前扫新建边编号 if(usedEdge[i]){ //如果这条边被使用 usedEdge[cancle[i].id]++; //这条边的使用情况+1 usedEdge[cancle[i].pre]--; //上一次用到这条边被取消 //相当于在上一次图中的有向环中的这个指向v顶点的有向边被取消 } } return res; } int main() { while(~scanf("%d%d", &n, &m)){ for(int i = 0; i < m; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; edge[i] = Edge(u, v, w, w, i); } NV = n, NE = m; int ans = ZLEdmonds(0); if(ans == -1 || ans == 0) printf("%d\n", ans); else { printf("%d\n", ans); for(int i = 0; i < m; i++){ if(edge[i].ww == 1 && usedEdge[i]) printf("%d ", i + 1); } printf("\n"); } } return 0; }
相关文章推荐
- 最小树形图模板朱刘算法分享
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- codeforces 618C. Constellation
- Codeforces Round #349 (Div. 2) - C
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces Round332 部分题解
- CodeForces 603A_Alternative Thinking (DP)
- CodeForces 602B_Approximating a Constant Range_DP
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)
- Codeforces #264(div 2)D.Gargari and Permutations
- Codeforces Round #236 (Div. 2)------A,B