一个有向图。选择最少的路径覆盖所有点。在路径最少的情况下,使得所有路径经过的边的权值之和最小。
const int maxn = 5000 ; const int maxm = 50000 ; const int inf = 1000000000 ; struct Edge{ int u , v , f , w , next , flow ; Edge(){} Edge(int _v , int _f , int _w , int _next):v(_v),f(_f),w(_w),next(_next){} }; int g[maxn + 10] ; Edge e[maxm + 10] ; int source , meet ; int id ; void add(int u , int v , int f , int w){ e[++id] = Edge(v , f , w , g[u]) ; e[id].u = u ; e[id].flow = 0 ; g[u] = id ; e[++id] = Edge(u , 0 , -w , g[v]) ; e[id].u = v ; e[id].flow = 0 ; g[v] = id ; } queue<int> que ; bool in[maxn + 10] ; int dist[maxn + 10] ; int pv[maxn + 10] , pe[maxn + 10] ; int bfs(){ while(! que.empty()) que.pop() ; que.push(source) ; memset(dist , 63 , sizeof(dist)) ; dist[source] = 0 ; in[source] = 1 ; while(! que.empty()){ int u = que.front() ; que.pop() ; in[u] = 0 ; for(int i = g[u] ; i ; i = e[i].next){ int v = e[i].v ; if(e[i].f - e[i].flow > 0 && dist[u] + e[i].w < dist[v]){ dist[v] = dist[u] + e[i].w ; pv[v] = u ; pe[v] = i ; if(! in[v]){ in[v] = 1 ; que.push(v) ; } } } } return dist[meet] < inf ; } int augment(){ int u = meet ; int delta = inf ; while(u != source){ delta = min(delta , e[pe[u]].f - e[pe[u]].flow) ; u = pv[u] ; } u = meet ; while(u != source){ e[pe[u]].flow += delta ; e[pe[u] ^ 1].flow -= delta ; u = pv[u] ; } return dist[meet] * delta ; } int mincostflow(){ int ans = 0 ; while(bfs()) ans += augment() ; return ans ; } void init(){ memset(g , 0 , sizeof(g)) ; id = 1 ; } int father[maxn] , next[maxn] ; vector<int> lis[maxn] ; int main(){ int i , j , n , m , u , v , w , t ; init() ; cin>>n>>m ; source = 2*n + 1 ; meet = 2*n + 2 ; for(i = 1 ; i <= n ; i++) add(source , i , 1 , 0) ; for(i = 1 ; i <= n ; i++) add(i+n , meet , 1 , 0) ; for(i = 1 ; i <= m ; i++){ scanf("%d%d%d" , &u ,&v ,&w) ; add(u , v+n , 1 , w) ; } w = mincostflow() ; t = 0 ; memset(father , 0 , sizeof(father)) ; memset(next , 0 , sizeof(next)) ; for(i = 2 ; i <= id ; i++){ if(e[i].f == e[i].flow && 1 <= e[i].u && e[i].u <= n && n <= e[i].v && e[i].v <= 2*n){ father[e[i].v - n] = e[i].u ; next[e[i].u] = e[i].v - n ; } } for(i = 1 ; i <= n ; i++) lis[i].clear() ; t = 0 ; for(i = 1 ; i <= n ; i++){ if(father[i] == 0){ t++ ; u = i ; while(u){ lis[t].push_back(u) ; u = next[u] ; } } } printf("%d %d\n" , t , w) ; for(i = 1 ; i <= t ; i++){ printf("%d" , lis[i].size()) ; for(j = 0 ; j < lis[i].size() ; j++) printf(" %d" , lis[i][j]) ; printf("\n") ; } return 0 ; }