[最小生成树] Codeforces 632F Educational Codeforces Round 9 F. Magic Matrix & SRM 687 div1 AllGraphCuts
2017-07-09 08:09
399 查看
Magic Matrix
把a矩阵当成邻接矩阵,设b为两点间路径最大值的最小值,那么ai,j≥bi,j,然后ai,j≤max(ai,k1,ak1,k2,⋯,akm,j),所以ai,j≤bi,j那么a=b,求b只要取最小生成树即可
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=2505; struct edge{ int u,v,w,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int w){ int p=++inum; G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } #define V G[p].v int n; int w ; int dis ,pre ,vst ; inline void Prim(){ dis[1]=0; for (int i=2;i<=n;i++) dis[i]=1<<30; for (int i=1;i<=n;i++){ int k=0; for (int j=1;j<=n;j++) if (!vst[j]) if (!k || dis[j]<dis[k]) k=j; vst[k]=1; if (pre[k]) add(pre[k],k,w[pre[k]][k]),add(k,pre[k],w[k][pre[k]]); for (int j=1;j<=n;j++) if (!vst[j] && dis[j]>w[k][j]) dis[j]=w[k][j],pre[j]=k; } } int b ; inline void dfs(int u,int fa,int z){ for (int p=head[u];p;p=G[p].next) if (V!=fa) b[z][V]=max(b[z][u],G[p].w),dfs(V,u,z); } int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) read(w[i][j]); for (int i=1;i<=n;i++) if (w[i][i]) return printf("NOT MAGIC\n"),0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (w[i][j]!=w[j][i]) return printf("NOT MAGIC\n"),0; Prim(); for (int i=1;i<=n;i++) dfs(i,0,i); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (w[i][j]!=b[i][j]) return printf("NOT MAGIC\n"),0; printf("MAGIC\n"); return 0; }
PS.还可以压位过,O(n3W)
AllGraphCuts
全局最小割,联想到最小割树,ai,j就是最小割树上的最小边,同理可以转化成一颗最大生成树// BEGIN CUT HERE #include<conio.h> #include<sstream> // END CUT HERE #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<string> #include<set> #define pb push_back #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; const int N=2505; struct edge{ int u,v,w,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int w){ int p=++inum; G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } #define V G[p].v int n; int w ; int dis ,pre ,vst ; inline void Prim(){ dis[1]=0; for (int i=2;i<=n;i++) dis[i]=-1<<30; for (int i=1;i<=n;i++){ int k=0; for (int j=1;j<=n;j++) if (!vst[j]) if (!k || dis[j]>dis[k]) k=j; vst[k]=1; if (pre[k]) add(pre[k],k,w[pre[k]][k]),add(k,pre[k],w[k][pre[k]]); for (int j=1;j<=n;j++) if (!vst[j] && dis[j]<w[k][j]) dis[j]=w[k][j],pre[j]=k; } } int b ; inline void dfs(int u,int fa,int z){ for (int p=head[u];p;p=G[p].next) if (V!=fa) b[z][V]=min(b[z][u],G[p].w),dfs(V,u,z); } class AllGraphCuts{ public: vector <int> findGraph(vector <int> x){ n=sqrt(x.size()); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) w[i][j]=x[(i-1)*n+(j-1)]; for (int i=1;i<=n;i++) if (w[i][i]) return {-1}; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (w[i][j]!=w[j][i]) return {-1}; Prim(); for (int i=1;i<=n;i++) b[i][i]=1<<30,dfs(i,0,i),b[i][i]=0; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (w[i][j]!=b[i][j]) return {-1}; vector<int> ans; for (int p=1;p<=inum;p+=2) ans.pb(G[p].w*n*n+(G[p].u-1)*n+(G[p].v-1)); return ans; } // BEGIN CUT HERE public: void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); if ((Case == -1) || (Case == 5)) test_case_5(); } private: template <typename T> string print_array(const vector<T> &_V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = _V.begin(); iter != _V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); } void verify_case(int Case, const vector <int> &Expected, const vector <int> &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: " << print_array(Expected) << endl; cerr << "\tReceived: " << print_array(Received) << endl; } } void test_case_0() { int Arr0[] = {0,1, 1,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {6 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(0, Arg1, findGraph(Arg0)); } void test_case_1() { int Arr0[] = {0,1, 1,1}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {-1 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(1, Arg1, findGraph(Arg0)); } void test_case_2() { int Arr0[] = {0,2,2, 2,0,2, 2,2,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {10, 11, 14 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(2, Arg1, findGraph(Arg0)); } void test_case_3() { int Arr0[] = {0,1,2,3,4, 1,0,2,3,4, 1,2,0,3,4, 1,2,3,0,4, 1,2,3,4,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {-1 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(3, Arg1, findGraph(Arg0)); } void test_case_4() { int Arr0[] = {0,0,0,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {2 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(4, Arg1, findGraph(Arg0)); } void test_case_5() { int Arr0[] = { 0, 2545, 2348, 2993, 2606, 2623, 2013, 3001, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 2827, 3044, 3082, 2545, 0, 2348, 2545, 2545, 2545, 2013, 2545, 2545, 2440, 2495, 2262, 2342, 2545, 2545, 2545, 2545, 2545, 2545, 2545, 2348, 2348, 0, 2348, 2348, 2348, 2013, 2348, 2348, 2348, 2348, 2262, 2342, 2348, 2348, 2348, 2348, 2348, 2348, 2348, 2993, 2545, 2348, 0, 2606, 2623, 2013, 2993, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 2827, 2993, 2993, 2606, 2545, 2348, 2606, 0, 2606, 2013, 2606, 2606, 2440, 2495, 2262, 2342, 2606, 2606, 2606, 2606, 2606, 2606, 2606, 2623, 2545, 2348, 2623, 2606, 0, 2013, 2623, 2623, 2440, 2495, 2262, 2342, 2617, 2623, 2623, 2623, 2623, 2623, 2623, 2013, 2013, 2013, 2013, 2013, 2013, 0, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 3001, 2545, 2348, 2993, 2606, 2623, 2013, 0, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 2827, 3001, 3001, 2626, 2545, 2348, 2626, 2606, 2623, 2013, 2626, 0, 2440, 2495, 2262, 2342, 2617, 2626, 2626, 2626, 2626, 2626, 2626, 2440, 2440, 2348, 2440, 2440, 2440, 2013, 2440, 2440, 0, 2440, 2262, 2342, 2440, 2440, 2440, 2440, 2440, 2440, 2440, 2495, 2495, 2348, 2495, 2495, 2495, 2013, 2495, 2495, 2440, 0, 2262, 2342, 2495, 2495, 2495, 2495, 2495, 2495, 2495, 2262, 2262, 2262, 2262, 2262, 2262, 2013, 2262, 2262, 2262, 2262, 0, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2262, 2342, 2342, 2342, 2342, 2342, 2342, 2013, 2342, 2342, 2342, 2342, 2262, 0, 2342, 2342, 2342, 2342, 2342, 2342, 2342, 2617, 2545, 2348, 2617, 2606, 2617, 2013, 2617, 2617, 2440, 2495, 2262, 2342, 0, 2617, 2617, 2617, 2617, 2617, 2617, 2773, 2545, 2348, 2773, 2606, 2623, 2013, 2773, 2626, 2440, 2495, 2262, 2342, 2617, 0, 2662, 2736, 2773, 2773, 2773, 2662, 2545, 2348, 2662, 2606, 2623, 2013, 2662, 2626, 2440, 2495, 2262, 2342, 2617, 2662, 0, 2662, 2662, 2662, 2662, 2736, 2545, 2348, 2736, 2606, 2623, 2013, 2736, 2626, 2440, 2495, 2262, 2342, 2617, 2736, 2662, 0, 2736, 2736, 2736, 2827, 2545, 2348, 2827, 2606, 2623, 2013, 2827, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 0, 2827, 2827, 3044, 2545, 2348, 2993, 2606, 2623, 2013, 3001, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 2827, 0, 3044, 3082, 2545, 2348, 2993, 2606, 2623, 2013, 3001, 2626, 2440, 2495, 2262, 2342, 2617, 2773, 2662, 2736, 2827, 3044, 0 } ; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {76801, 87602, 76403, 15604, 14005, 14406, 95607, 14408, 45609, 54010, 113211, 102812, 53613, 72414, 10015, 90416, 110417, 108818, 76819, 20022, 5223, 16824, 14025, 20426, 37227, 115628, 118829, 105230, 39631, 114032, 70833, 2434, 9235, 71636, 3637, 108438, 68439, 16443, 24444, 37245, 54046, 118447, 46048, 13249, 38450, 27651, 23652, 105253, 76054, 22455, 112056, 5657, 82458, 28859, 31264, 117665, 73666, 91667, 11268, 67269, 110870, 18471, 114872, 119673, 22074, 86075, 44876, 22477, 74478, 93679, 96085, 8486, 59687, 110088, 1689, 107290, 56091, 56092, 74893, 61294, 109295, 109296, 18097, 66498, 20899, 12506, 98907, 82908, 77309, 51710, 110111, 108112, 22513, 66514, 43315, 36516, 19717, 15318, 26519, 34127, 70128, 8929, 20930, 131, 81732, 80133, 29334, 68935, 53336, 81737, 36538, 57739, 35348, 96149, 25750, 19351, 15752, 4153, 80554, 107355, 96556, 70557, 66958, 48559, 33769, 81370, 55771, 15372, 61373, 72574, 11375, 2976, 66577, 108178, 57779, 590, 78991, 14992, 10593, 69794, 47395, 33796, 113397, 77398, 68999, 77811, 28212, 12613, 64614, 80215, 9816, 27017, 30618, 73819, 46632, 66633, 7834, 100635, 636, 7437, 4238, 76639, 87453, 16254, 10255, 31856, 50257, 18258, 3459, 73474, 69475, 63876, 41077, 3878, 28679, 13495, 56696, 109497, 101098, 116699, 60316, 107517, 12318, 98719, 51137, 91138, 81139, 108358, 119959, 106379 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); verify_case(5, Arg1, findGraph(Arg0)); } // END CUT HERE }; // BEGIN CUT HERE int main(){ AllGraphCuts ___test; ___test.run_test(5); getch() ; return 0; } // END CUT HERE
相关文章推荐
- [LCT维护最小生成树 || CDQ分治 || 线段树 并查集 dfs树] Codeforces 603E #334 (Div. 1) E. Pastoral Oddities
- CodeForces 827D Round #423 Div2F&Div1D:LCA+路径压缩+MST(最小生成树)
- 【Python排序搜索基本算法】之无向图的最小割&Karger算法(Graphs and Minimum Cuts & Karger's Min-Cut Algorithm)
- 【BZOJ1016】【JSOI2008】最小生成树计数 & 【BZOJ1543】生成树计数 (kruskal+matrix_tree定理)
- Codeforces 136 divIID && zoj 3633 && HDU 4358
- HDOJ 1162 Eddy's picture(最小生成树 - kruskal)
- 简化document.createElement("div")动态生成层方法
- http://acm.nyist.net/JudgeOnline/problem.php?pid=38&&最小生成树
- 贪心算法(Greedy Algorithm)之最小生成树 克鲁斯卡尔算法(Kruskal's algorithm)
- hdu&nbsp;4081&nbsp;最小生成树变形
- hdu 4313 Matrix (最小生成树krusual)
- 简化document.createElement("div")动态生成层方法 (转)
- 求图的绝对中心 && 最小直径生成树 MDST
- 最小生成树(kruskal&prim)畅通工程
- POJ1258--贪心&最小生成树的prim算法
- srm 558 div1 1000 SurroundingGame(最小割构图题)
- 【区别】最短路&最小生成树
- Gridview中生成的属性rules="all",在Firefox出现内线框解决办法
- srm 535 div2 250&500
- sgu529. It's Time to Repair the Roads 简化版动态最小生成树