jscpc 2022 B(网络流+构造)

B. Prime Ring Plus

link

因为 define int long long 边数开小 狂wa
在这里插入图片描述

我们将原点向 奇数连 2的流量
偶数想 汇点连2的流量
奇数和偶数能凑成质数的话 连 1的流量
跑最大流
如果 两个数之间的流量为0了证明可以在一个环
我们用度数去判断是否有解

#include <bits/stdc++.h>
using namespace  std;
//#define  int long long
typedef long long ll;
typedef pair<int, int> pii;
#define x first
#define y second
#define pb  push_back
#define inf 1e18
#define IOS   std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define  fer(i,a,b)  for(int i=a;i<=b;i++)
#define  der(i,a,b)  for(int i=a;i>=b;i--)
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
int qmi( int a, int b ) {
  int res = 1;
  while( b ) {
    if( b & 1 ) res = res * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}
const int N = 1e6 + 10;
int dr[4][2] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}};
int n, k;
const int V = 20010;
const int E = 1e7+10;
int p[N];
int vis[N];
int cnt;
void  init( int n = 20001 ) {
  for( int i = 2; i <= n; i++ ) {
    if( !vis[i] )p[cnt++] = i;
    for( int j = 0; j < cnt && i * p[j] <= n; j++ ) {
      vis[i * p[j]] = 1;
      if( i % p[j] == 0 )break;
    }
  }
  return ;
}
template<typename T>
struct FlowGraph {
  int s, t, vtot;
  int h[V], idx;
  int d[V], cur[V];
  int e[E * 2];
  int ne[E * 2];
  int f[E * 2];
  /*struct edge {
  	int v, nxt;
  	T f;
  } e[E * 2];
  void addedge(int u,int v, T f){
  	e[etot]= {v, head[u], f}; head[u] = etot++;
  	e[etot]= {u, head[v], 0}; head[v] = etot++;
  }*/
  void add( int a, int b, int c ) {
    e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;
    e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
  }

  bool bfs() {
    for ( int i = 1; i <= vtot; i++ ) {
      d[i] = 0;
      cur[i] = h[i];
    }
    queue<int> q;
    q.push( s );
    d[s] = 1;
    while ( !q.empty() ) {
      int u = q.front();
      q.pop();
      for ( int i = h[u]; ~i; i = ne[i] ) {
        int v = e[i];
        if ( f[i] && !d[v] ) {
          d[v] = d[u] + 1;
          if ( v == t ) return true;
          q.push( v );
        }
      }
    }
    return false;
  }

  /*	T dfs(int u, T m) {
  		if (u == t) return m;
  		T flow = 0;
  		for (int i = cur[u]; ~i; cur[u] = i = ne[i]){
  			int v=e[i];
  			if (f[i] && d[v] == d[u] + 1) {
  				T t = dfs(v, min(m-flow, f[i]));
  				if(!t)d[v]=-1;
  				f[i] -= t;
  				f[i ^ 1] += t;
  				flow+=t;
  			}
  		}
  		return flow;
      }*/

  T dfs( int u, T m ) {
    if ( u == t ) return m;
    T flow = 0;
    for ( int i = cur[u]; ~i; cur[u] = i = ne[i] )
      if ( f[i] && d[e[i]] == d[u] + 1 ) {
        T t = dfs( e[i], min( m, f[i] ) );
        f[i] -= t;
        f[i ^ 1] += t;
        m -= t;
        flow += t;
        if ( !m ) break;
      }
    if ( !flow ) d[u] = -1;
    return flow;
  }
  T dinic() {
    T flow = 0;
    while ( bfs() ) flow += dfs( s, numeric_limits<T>::max() );
    return flow;
  }
  void init( int s_, int t_, int vtot_ ) {
    s = s_;
    t = t_;
    vtot = vtot_;
    idx = 0;
    for ( int i = 1; i <= vtot; i++ ) h[i] = -1;
  }
};

FlowGraph<int> G;
vector<array<int, 3>>ve;
int ans;
vector<int>res[N];
vector<int>g[N];
int d[N];
int v[N];
void dfs( int u ) {
  v[u] = 1;
  res[ans].push_back( u );
  for( auto t : g[u] ) {
    if( !v[t] )dfs( t );
  }
}
int s, t;
void solve() {
  cin >> n;
  init();
  s = n + 1;
  t = n + 2;
  G.init( s, t, t );
  for( int i = 1; i <= n; i++ ) {
    if( i & 1 )G.add( s, i, 2 );
    else G.add( i, t, 2 );
  }
  for( int i = 1; i <= n; i += 2 ) {
    for( int j = 1; j <= n / 2; j++ ) {
      if( !vis[i + 2 * j] ) {
        ve.push_back( {i, 2 * j, G.idx} );
        G.add( i, 2 * j, 1 );
      }
    }
  }
  bool  f = 1;
  int ttt = G.dinic();
  if(ttt!=n)f=0;
  for( auto v : ve ) {
    if( !G.f[v[2]] ) {
      g[v[0]].push_back( v[1] );
      g[v[1]].push_back( v[0] );
      d[v[0]]++;
      d[v[1]]++;
    }
  }

  for( int i = 1; i <= n; i++ ) {
    if( d[i] != 2 ) {
      f = 0;
      break;
    }
  }
  if( !f ) {
    cout << -1 << endl;
    return ;
  }
  for( int i = 1; i <= n; i++ ) {
    if( !v[i] ) {
      ans++;
      dfs( i );
    }
  }
  cout << ans << endl;
  for( int i = 1; i <= ans; i++ ) {
    cout << res[i].size() << " ";
    for( auto v : res[i] ) {
      cout << v;
      if( v == res[i].back() )cout << endl;
      else   cout<<" ";
      // cout<<v<<(v==res[i].back()?'\n':" ");
    }
  }

}
int main() {
  IOS;
  int _ = 1;
  //cin>>_;
  while( _-- )
    solve();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值