The main idea: give a picture of a few of the one-way side, the rest of the side arbitrary orientation. How many ternary rings can be formed.
Idea: For any three points, they are composed of ternary rings, when and only if these points are in degrees = degrees = 1. If there is no ternary ring, just change the direction of any one of these sides, so that a point into the degree of 2, a point of the degree of 2. We just need to figure out how many of the three points have a point in the degree of 2 to be able to, and minimize this thing.
By formula:ans=c (n,3)-σc (degree[x],2), we can find that we only need to make each point as small as possible. Think of the cost flow model (I can't think of it). )
Similar to x^2 such as a function to join the cost stream diagram, you can find that f[2]-f[1] = 3.f[3]-f[2] = 5 .... All we need is a 1,3,5,7 ... these sides add in the line. The cost flow will certainly be from small to large flow, meet f[x] = x^2.
Remember to see a puzzle, said the afternoon, and then the local test is not a, in a good way to hand over, and then a.
You know why?
This problem has SPJ Ah!!!
Do you know why I noticed it???
Because my * * * also tuned for an afternoon Ah!!!
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include < algorithm> #define INF 0x3f3f3f3f#define MAX 20010#define maxe 5000010#define S 0#define T (MAX-1) using namespace std; #define MIN (a) < (b)? (a):(B) #define MAX (a) (a) > (b)? (a):(B)) struct mincostmaxflow{int head[max],total; int Next[maxe],last[maxe],aim[maxe],flow[maxe],cost[maxe]; int F[max],from[max],p[max]; BOOL V[max]; Mincostmaxflow () {total = 1; memset (head,0,sizeof (head)); } void Add (int x,int y,int f,int c) {next[++total] = head[x]; Aim[total] = y; Last[total] = x; Flow[total] = f; Cost[total] = c; HEAD[X] = total; } void Insert (int x,int y,int f,int c) {Add (x,y,f,c); ADD (Y,X,0,-C); } bool Spfa () {static queue<int> q; while (!q.empty ()) Q.pop (); memset (F,0x3f,sizeof (f)); memset (v,false,sizeof (v)); F[s] = 0; Q.push (S); while (!q.empty ()) {int x = Q.front (); Q.pop (); V[X] = false; for (int i = head[x]; i; i = Next[i]) if (Flow[i] && f[aim[i]] > F[x] + cost[i]) { F[aim[i]] = f[x] + cost[i]; if (!v[aim[i]]) {V[aim[i]] = true; Q.push (Aim[i]); } From[aim[i]] = x; P[aim[i]] = i; }} return f[t]! = INF; } int Edmondskarp () {int re = 0; while (SPFA ()) {int max_flow = INF; for (int i = T; i = S; i = from[i]) max_flow = min (max_flow,flow[p[i]]); for (int i = T; i = S; i = From[i]) {Flow[p[i]]-= Max_flow; FLOW[P[I]^1] + = Max_flow; } Re + = Max_flow * F[t]; } return re; }}solver; int Cnt,total;int src[110][110],T;pair<int,int> fight[max];int In[max];int ans[110][110]; int DFS (int x) {if (x > Total) return x-total; for (int i = solver.head[x]; i; i = Solver.next[i]) {if (i&1 | | solver.flow[i]) continue; Return DFS (Solver.aim[i]); } return 0;} int main () {CIN >> cnt; Total = cnt * (cnt-1)/2; for (int i = 1; l <= CNT; ++i) for (int x,j = 1; j <= cnt; ++j) {scanf ("%d", &x); if (J <= i) continue; Fight[++t] = Make_pair (I,J); if (x = = 2) ++in[i],++in[j],solver. Insert (T,i + total,1,0), Solver. Insert (t,j + total,1,0); else if (!x) ++in[j],solver. Insert (t,j + total,1,0); Else ++in[i],solver. Insert (t,i + total,1,0); } for (int i = 1; I <= total; ++i) solver. Insert (s,i,1,0); for (int i = 1; I <= cnt, ++i) for (int j = 1; J <= In[i]; ++j) solver. Insert (Total + i,t,1, (J << 1)-1); cout << (CNT * (cnt-1) * (CNT-2)/3 + total-solver. Edmondskarp ())/2 << Endl; for (int i = 1; I <= total; ++i) {int win = DFS (i); Ans[fight[i].first][fight[i].second] = (win = = Fight[i].first); Ans[fight[i].second][fight[i].first] = (win! = Fight[i].first); } for (int i = 1; l <= CNT; ++i) for (int j = 1; j <= cnt; ++j) printf ("%d%c", ans[i][j], "\ n" [j = = cnt]); return 0;}
Bzoj 2597 WC2007 Scissors stone cloth cost flow