「日常訓練」Battle Over Cities - Hard Version(PAT-TOP-1001)
阿新 • • 發佈:2018-11-05
syn 否則 battle find lse name ret long begin
題意與分析
題意真的很簡單,實在不想講了,簡單說下做法吧。
枚舉刪除每個點,然後求最小生成樹,如果這個路已經存在那麽邊權就是0,否則按照原來的處理,之後求花費,然後判整個圖是否聯通(並查集有幾個root),如果不聯通直接硬點花費是INF,然後處理輸出答案即可。
一道最小生成樹的模板題,比較有學習的意義。
代碼
/* * Filename: pat_top_1001.cpp * Date: 2018-11-05 */ #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define PB emplace_back #define MP make_pair #define fi first #define se second #define rep(i,a,b) for(repType i=(a); i<=(b); ++i) #define per(i,a,b) for(repType i=(a); i>=(b); --i) #define ZERO(x) memset(x, 0, sizeof(x)) #define MS(x,y) memset(x, y, sizeof(x)) #define ALL(x) (x).begin(), (x).end() #define QUICKIO ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr) using namespace std; using pi=pair<int,int>; using repType=int; using ll=long long; using ld=long double; using ull=unsigned long long; const int MAXN=505,MAXM=125005; int n,m; struct Edge { int u,v,w; bool ok; Edge(int _u, int _v, int _w, bool _o): u(_u), v(_v), w(_w), ok(_o) {} }; vector<Edge> edges; vector<int> G[MAXN]; void add_edge(int u, int v, int w, bool ok) { edges.PB(u,v,w,ok); G[u].PB(int(edges.size())-1); } int edges_ord[MAXM]; int pa[MAXN]; int find_pa(int x) { return pa[x]==x?x:pa[x]=find_pa(pa[x]); } bool union_pa(int x,int y) { int fx=find_pa(x), fy=find_pa(y); if(fx!=fy) pa[fx]=fy; else return false; return true; } int kruskal(int nope_pnt) { int ans=0; iota(pa+1, pa+n+1, 1); rep(i,0,m-1) { int u=edges[edges_ord[i]].u, v=edges[edges_ord[i]].v, w=edges[edges_ord[i]].w; bool ok=edges[edges_ord[i]].ok; if(u==nope_pnt || v==nope_pnt) continue; if(union_pa(u,v)) ans+=(1-ok)*w; } int cnt=0; rep(i,1,n) if(i!= nope_pnt && find_pa(i)==i) cnt++; if(cnt==1) return ans; else return INF; } int main() { scanf("%d%d", &n,&m); rep(i,1,m) { int u,v,w,o; scanf("%d%d%d%d", &u, &v, &w, &o); add_edge(u,v,w,o==1); } iota(edges_ord, edges_ord+m, 0); vector<int> ans_pnt; int ans_val=0; sort(edges_ord, edges_ord+m, [&](int x, int y) -> bool { if((1-edges[x].ok)*edges[x].w== edges[y].w*(1-edges[y].ok)) return (edges[x].u<edges[y].u || (edges[x].u==edges[y].u && edges[x].v<edges[y].v)); else return (1-edges[x].ok)*edges[x].w< edges[y].w*(1-edges[y].ok); }); rep(nope_pnt,1,n) { int ans_tmp=kruskal(nope_pnt); if(ans_tmp>ans_val) { ans_val=ans_tmp; ans_pnt.clear(); ans_pnt.PB(nope_pnt); } else if(ans_tmp==ans_val) ans_pnt.PB(nope_pnt); } if(ans_val==0) printf("0"); else { rep(i,0,int(ans_pnt.size())-1) { printf("%d", ans_pnt[i]); if(i==int(ans_pnt.size())-1) printf("\n"); else printf(" "); } } return 0; }
「日常訓練」Battle Over Cities - Hard Version(PAT-TOP-1001)