Three in a row of singles

Posted by gregolson on Mon, 22 Jul 2019 13:40:50 +0200

This is the final chapter, permanent missing.

Main idea of the title:

There are N cards, each card has numbers on both sides, ranging from 1 to 2 N. Find the least number of inversions, so that each card has different numbers on the upward side, and find out the number of solutions to achieve this effect. (multi-test, each card faces upward at the beginning, with unsolvable output "-1-1")

Solutions:

20% data (N<=20)

Direct search is enough.

100% data (N<=1*105)

Search complexity is not allowed. We try to abstract this problem.

If the number on the card is abstracted as a point and the card is abstracted as a edge, the problem will be transformed into:

For a digraph, some edges are flipped so that the entrance of each point is less than or equal to 1.

First connect the edges, we find that the whole map has at most 2N points, but only N edges. This means that the connectivity of graphs is very poor. Graphs are divided into many interconnection blocks. Then we discuss each interconnection block by classification.

Let the number of edges of the connected block be e and the number of points be v.

If e < v, the whole picture must have no solution. According to the drawer principle, at least one point has a degree of entry greater than 1.

If e=v, the graph is a base ring tree, and the vertex penetration on the ring cannot be zero, because the vertex on the ring must be pointed at by the point on the other ring. If the condition is satisfied, it must be a base-extroverted tree.

If e=v+1, the graph is a tree, and it can be used twice to find the minimum cost required.

For the first time, a point is selected for dfs, which is updated by the son to the father. If the DFS passes through an opposite side, add 1 to the f array. If the DFS is a base ring tree, it also needs to record an unused side to prevent the path of the second DFS from being different from that of the first one. Then, for the second time, the father updates the son. If it passes through the opposite side, add 1 to the G array and subtract 1 from it. The g and f arrays are equal at the root of the search tree.

In the second dfs, the g value of each node is pressed into a vector, and then sort it. The first is the minimum, and the number of solutions is the same as the minimum.

Finally multiply.

Single complexity O (NlogN)

Code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<algorithm>
  6 #define LL long long
  7 using namespace std;
  8 const int N=100010;
  9 const LL mod=998244353;
 10 int t,n,m=1,mv=0,me=0,cnt=0,tot=0,top=0,start,endd,bridge;
 11 int fi[N<<1],g[N<<1],f[N<<1];
 12 bool v[N<<1],vis[N<<1];
 13 struct edge{
 14     int u,v,ne;
 15 }e[N<<1];
 16 vector<int> gg;
 17 void add(int x,int y)
 18 {
 19     e[++m].u=x;
 20     e[m].v=y;
 21     e[m].ne=fi[x];
 22     fi[x]=m;
 23 }
 24 int read()
 25 {
 26     int s=0;
 27     char c=getchar();
 28     while(c<'0'||c>'9')    c=getchar();
 29     while(c>='0'&&c<='9'){
 30         s=(s<<3)+(s<<1)+c-'0';
 31         c=getchar();
 32     }
 33     return s;
 34 }
 35 void clean()
 36 {
 37     memset(fi,0,sizeof(fi));
 38     memset(e,0,sizeof(e));
 39     memset(f,0,sizeof(f));
 40     memset(g,0,sizeof(g));
 41     memset(v,false,sizeof(v));
 42     memset(vis,false,sizeof(vis));
 43     m=1;top=tot=cnt=0;
 44 }
 45 void dfs(int x)
 46 {
 47     v[x]=true;mv++;
 48     for(int i=fi[x];i!=0;i=e[i].ne){
 49         int y=e[i].v;
 50         me++;
 51         if(v[y]) continue;
 52         dfs(y);
 53     }
 54 }
 55 void dfs1(int x,int p)
 56 {    
 57     vis[x]=true;
 58     for(int i=fi[x];i!=0;i=e[i].ne){
 59         int y=e[i].v;
 60         if(y==p) continue;
 61         if(vis[y]){
 62             start=x;endd=y;bridge=i;
 63         }
 64         else{
 65             dfs1(y,x);
 66             f[x]+=f[y]+(i&1);
 67         }
 68     }
 69 }
 70 void dfs2(int x,int p)
 71 {
 72     gg.push_back(g[x]);
 73     for(int i=fi[x];i!=0;i=e[i].ne){
 74         int y=e[i].v;
 75         if(y==p||i==bridge||i==(bridge^1)) continue;
 76         g[y]=g[x]+((i&1)==1?-1:1);
 77         dfs2(y,x);
 78     }
 79 }
 80 int main()
 81 {
 82     t=read();
 83     while(t--)
 84     {
 85         clean();
 86         n=read();
 87         for(int i=1;i<=n;i++){
 88             int x=read(),y=read();
 89             add(y,x);add(x,y);
 90         }
 91         int flag=0;
 92         for(int i=1;i<=2*n;i++){
 93             if(!v[i]){
 94                 mv=me=0;
 95                 dfs(i);
 96                 if(me/2>mv){
 97                     printf("-1 -1\n");
 98                     flag=1;break;
 99                 }
100             }
101         }
102         if(flag==1)    continue;
103         int ans1=0;LL ans2=1;
104         for(int i=1;i<=2*n;i++){
105             if(!vis[i]){
106                 LL num=0;start=endd=bridge=0;
107                 gg.clear();
108                 dfs1(i,0);
109                 g[i]=f[i];
110                 dfs2(i,0);
111                 if(bridge==0){
112                     sort(gg.begin(),gg.end());
113                     ans1+=gg[0];
114                     for(int j=0;j<gg.size();j++){
115                         if(gg[j]!=gg[0]) break;
116                         num++;
117                     }
118                 }
119                 else{
120                     bridge&=1;
121                     if(g[start]+(bridge^1)==g[endd]+bridge) num=2;
122                     else num=1;
123                     ans1+=min(g[start]+(bridge^1),g[endd]+bridge); 
124                 }
125                 ans2=ans2*num%mod;
126             }
127         }
128         printf("%d %lld\n",ans1,ans2);
129     }
130     return 0;
131 }

Topics: PHP less