• 暑期实战训练


    8.19/8/21 [4/4]
    A.模拟 B.贪心 C.贪心第一个>=5的,模拟
    E.线段树维护矩阵快速幂结果,每个节点保存一个2x2的递推矩阵,利用矩阵乘法结合律a*b+a*c=a*(b+c)区间维护
    #include<bits/stdc++.h>
    #define ll long long
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=1e5+10;
    const ll mod=1e9+7;
    int n,m;
    class matrix{public://mod
      ll x[2][2];
      void e(){memset(x,0,sizeof x);x[0][0]=x[1][1]=1;}
      void fill(){x[0][0]=x[1][0]=x[0][1]=1;x[1][1]=0;}
      matrix operator *(matrix &m){
        matrix ans;memset(ans.x,0,sizeof ans.x);
        rep(i,0,1)rep(j,0,1)rep(k,0,1)if(x[i][k]&&m.x[k][j])
          ans.x[i][j]=(ans.x[i][j]+x[i][k]*m.x[k][j])%mod;
        return ans;
      }
      matrix operator +(matrix &m){
        matrix ans;
        rep(i,0,1)rep(j,0,1)ans.x[i][j]=(x[i][j]+m.x[i][j])%mod;
        return ans;
      }
      matrix pow(ll p){
        matrix ans;ans.e();matrix t;t.fill();
        while(p){if(p&1) ans=t*ans;t=t*t;p>>=1;}return ans;
      }
    }xx,x0;
    matrix getp(ll n){return x0.pow(n);}
    class segtree{public:
    #define nd  node[now]
    #define ndl node[now<<1]
    #define ndr node[now<<1|1]
      struct segnode {int l,r;matrix x,tag;}node[maxn<<2|3];
      inline void pushup(int now){nd.x=ndl.x+ndr.x;}
      inline void pushdown(int now){
        ndl.tag=ndl.tag*nd.tag;
        ndr.tag=ndr.tag*nd.tag;
        ndl.x=ndl.x*nd.tag;
        ndr.x=ndr.x*nd.tag;
        nd.tag.e();
      }
      void maketree(int s,int t,int now=1){
        nd.l=s,nd.r=t;nd.tag.e();
        if(s==t) {
          int x;cin>>x;
          nd.x=x0.pow(x-1);
          return ;
        }
        maketree(s,(s+t)/2,now<<1);
        maketree((s+t)/2+1,t,now<<1|1);
        pushup(now);
      }
      void update(int s,int t,int now=1){
        if(s<=nd.l&&t>=nd.r) {
          nd.tag=nd.tag*xx;
          nd.x=nd.x*xx;
          return ;
        }
        pushdown(now);
        if(s<=ndl.r) update(s,t,now<<1);
        if(t>ndl.r) update(s,t,now<<1|1);
        pushup(now);
      }
      ll query(int s,int t,int now=1){
        if(s<=nd.l&&t>=nd.r) return nd.x.x[0][0];
        pushdown(now);
        ll sum=0;
        if(s<=ndl.r) sum+=query(s,t,now<<1);
        if(t>ndl.r) sum+=query(s,t,now<<1|1);
        return sum%mod;
      }
    }tree;
    int main(){
      x0.fill();
      cin>>n>>m;
      tree.maketree(1,n);
      int x,a,b;
      while(m--){
        cin>>x>>a>>b;
        if(x==1){
          cin>>x;xx=x0.pow(x);
          tree.update(a,b);
        }else cout<<tree.query(a,b)<<endl;
      }
    }
    

    7.19/8/11
    #578Div2 [6/6]
    A.模拟 B.贪心 C.先让n,m互质,然后每次看是否在同一段内
    D.二维差分前缀和,取一个最大值
    #include<bits/stdc++.h>
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    using namespace std;//head
    const int maxn=2e3+10,maxm=1e3+10;
    int casn,n,m,k;
    int pz[maxn][maxn],sum[maxn][maxn];
    int main() {IO;
      cin>>n>>k;
      if(n==k){cout<<2*n;return 0;}
      rep(i,1,n){
        string s;cin>>s;
        rep(j,1,n) pz[i][j]=(s[j-1]=='B');
      }
      rep(i,1,n){
        int mn=n+1,mx=0;
        per(j,1,n) if(pz[i][j])mn=j;
        rep(j,1,n) if(pz[i][j])mx=j;
        if(mx==0){
          sum[1][1]++;
          continue;
        }
        if(mx-mn+1<=k){
          int x1,x2,y1,y2;
          x1=max(1,i-k+1),x2=i+1;
          y1=max(1,mx-k+1),y2=mn+1;
          ++sum[x1][y1];
          --sum[x1][y2];
          --sum[x2][y1];
          ++sum[x2][y2];
        }
      }
      rep(i,1,n){
        int mn=n+1,mx=0;
        per(j,1,n) if(pz[j][i])mn=j;
        rep(j,1,n) if(pz[j][i])mx=j;
        if(mx==0){
          sum[1][1]++;
          continue;
        }
        if(mx-mn+1<=k){
          int x1,x2,y1,y2;
          x1=max(1,mx-k+1),x2=mn+1;
          y1=max(1,i-k+1),y2=i+1;
          ++sum[x1][y1];
          --sum[x1][y2];
          --sum[x2][y1];
          ++sum[x2][y2];
        }
      }
      rep(i,1,n) rep(j,1,n)
        sum[i][j]+=sum[i][j-1];
      rep(i,1,n) rep(j,1,n)
        sum[i][j]+=sum[i-1][j];
      int ans=0;
      rep(i,1,n) rep(j,1,n) ans=max(ans,sum[i][j]);
    
      cout<<ans<<endl;
    }
    

    E.维护ans的哈希,暴力匹配str的前缀和ans的后缀

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;//head
    const int maxn=3e6+10,maxm=1e3+10,mod=2520;
    int casn,n,m,k;
    int val[maxm],g[maxm][20],e[maxm],flag[maxm][mod+10];
    int to[maxm][mod+10],vis[maxm][mod+10];
    unordered_set<int> cnt;
    stack<pii> stk;
    int dfs(int now,int sum,int d=1){
      if(vis[now][sum]!=0) return vis[now][sum];
      stk.push(mp(now,d));
      if(flag[now][sum]!=0) {
        cnt.clear();
        while(!stk.empty()){
          pii x=stk.top();stk.pop();
          if(x.se<flag[now][sum]) break;
          cnt.insert(x.fi);
        }
        return vis[now][sum]=cnt.size();
      }
      flag[now][sum]=d;
      int x=(sum+val[now])%mod;
      return vis[now][sum]=dfs(to[now][x],x,d+1);
    }
    int main() {IO;
      cin>>n;
      rep(i,1,n) cin>>val[i];
      rep(i,1,n) val[i]=(val[i]%mod+mod)%mod;
      rep(i,1,n){
        cin>>k;e[i]=k;
        rep(j,0,k-1) cin>>g[i][j];
      }
      rep(i,1,n)rep(j,0,mod-1) to[i][j]=g[i][j%e[i]];
      rep(i,1,n)rep(j,0,mod-1){
        while(!stk.empty()) stk.pop();
        dfs(i,j);
      }
      cin>>m;
      while(m--){
        int x,y;cin>>x>>y;
        cout<<vis[x][(y%mod+mod)%mod]<<endl;
      }
    }
    

    6.19/8/12

    #375Div2 [5/5]

    A.快速幂取模 B.a^b=x 转化为 a^x=b C.求出所有的环长的LCM即可,注意长度为偶数的环要/2

    D. 并查集+裸背包DP E.每隔2加一条边,然后跑黑白染色


    5.19/8/11

    #376Div2 [6/6]

    A.模拟即可 B.贪心,先把奇数变成偶数 C.并查集,每个集合取最多颜色

    D.每两个相邻字符串,有一个合法的操作次数区间,区间求交

    E.问题转化为两个人轮流向后取一个前缀和,变成一个dp问题

    F.枚举起点,不断翻倍,取最大的和


    4.19/8/10

    #377Div2 [6/6] 

    A.最大-最小 B.字符串模拟 C.$O(n^2)$暴力填数 D.贪心每一个连通块

    E.奇数点必定为偶数个,两两建边,然后fleury求欧拉回路

    #include <bits/stdc++.h>
    #define endl '
    '
    #define fi first
    #define se second
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=2e2+10,maxm=1e5+10;
    int casn,n,m,k;
    struct node{int to,next;};
    node e[maxm];int head[maxn],nume;
    void init(int n=maxn-5){nume=0;fill_n(head,n+1,0);}
    void add(int a,int b){e[++nume]={b,head[a]};head[a]=nume;}
    stack<int> stk;
    vector<int>que;
    int cnt[maxn],used[maxm],vis[maxn];
    bool eg1[maxn][maxn],w[maxm],eg2[maxn][maxn],egv[maxn][maxn];
    void dfs(int now){
      stk.push(now);
      for(int i=head[now];i;i=e[i].next)if(!used[i]){
        int id=(i+1)/2;
        used[id*2]=used[id*2-1]=1;
        if(w[i]) {
          eg1[now][e[i].to]=1;
          eg2[now][e[i].to]=0;
          eg2[e[i].to][now]=0;
        }
        dfs(e[i].to);
        break;
      }
    }
    void dfss(int now){
      vis[now]=1;
      que.push_back(now);
      rep(i,1,n) if(!vis[i]&&eg2[i][now]) dfss(i);
    }
    void fleury(int now){
      stk.push(now);
      while(!stk.empty()){
        int flag=0;
        rep(i,1,n) if(eg2[stk.top()][i]>0) {
          flag=1;break;
        }
        if(!flag) stk.pop();
        else {
          int to=stk.top();
          stk.pop();
          dfs(to);
        }
      }
    }
    int main(){IO;
      cin>>casn;
      while(casn--){
        cin>>n>>m;
        memset(eg1,0,sizeof eg1);
        memset(eg2,0,sizeof eg2);
        memset(egv,0,sizeof egv);
        memset(cnt,0,sizeof cnt);
        init(n+2);
        int ans=n;
        rep(i,1,m) {
          int a,b;cin>>a>>b;
          eg2[a][b]=eg2[b][a]=1;
          egv[a][b]=egv[b][a]=1;
          cnt[a]++,cnt[b]++;
          add(a,b);used[nume]=0,w[nume]=1;
          add(b,a);used[nume]=0,w[nume]=1;
        }
        memset(vis,0,sizeof vis);
        rep(i,1,n){
          if(vis[i]) continue;
          que.clear();
          dfss(i);
          int la=0;
          rep(j,0,que.size()-1)if(cnt[que[j]]&1){
            ans--;
            if(la){
              add(que[j],la);used[nume]=0,w[nume]=0;
              add(la,que[j]);used[nume]=0,w[nume]=0;
              la=0;
            }else la=que[j];
          }
         while(!stk.empty()) stk.pop() ;
         fleury(que[0]);
        }
        cout<<ans<<endl;
        rep(i,1,n)rep(j,1,n) if(egv[i][j]&&!eg1[j][i]) {
          cout<<i<<' '<<j<<endl;
        }
      }
    }
    

     F.先移除s,t,求出森林,然后连接必须连s/t的,然后再连接s/t都可以的,最后连接st

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define all(x) x.begin(),x.end()
    #define pii pair<int,int>
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=5e5+20,maxm=1e6+10;
    int casn,n,m,k;
    vector<int>g[maxn];
    pii e[maxn];
    vector<pii> ans;
    int d[maxn];
    class ufs{public:
      int fa[maxn];
      void init(int n){rep(i,1,n+1) fa[i]=i;}
      int find(int now){return fa[now]==now?now:fa[now]=find(fa[now]);}
      inline void unite(int a,int b){fa[find(b)]=find(a);}
      inline bool same(int a,int b){return find(a)==find(b);}
    }dsu;
    int viss[maxn],vist[maxn],vis[maxn];
    int main(){
      int s,t,ds,dt;
      cin>>n>>m;
      dsu.init(n);
      rep(i,1,m) {
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
        e[i]={a,b};
      }
      cin>>s>>t>>ds>>dt;
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(a==s||a==t)continue;
        if(b==s||b==t)continue;
        if(!dsu.same(a,b)){
          dsu.unite(a,b);
          d[a]++;
          d[b]++;
          ans.push_back(e[i]);
        }
      }
      for(auto i:g[s])viss[dsu.find(i)]=1;
      viss[s]=1,vist[t]=1;
      for(auto i:g[t])vist[dsu.find(i)]=1;
      rep(i,1,n) if(!(viss[dsu.find(i)]||vist[dsu.find(i)]))
        {cout<<"No";return 0;}
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(a==s&&b!=t){
          int fa=dsu.find(b);
          if(!dsu.same(a,b)&&viss[fa]&&!vist[fa]&&!vis[fa]){
            dsu.unite(a,b);
            ans.push_back(e[i]);
            d[a]++,d[b]++;
            vis[fa]=1;
          }
        }else if(b==s&&a!=t){
          int fa=dsu.find(a);
          if(!dsu.same(a,b)&&viss[fa]&&!vist[fa]&&!vis[fa]){
            dsu.unite(a,b);
            d[a]++,d[b]++;
            ans.push_back(e[i]);
            vis[fa]=1;
          }
        }
      }
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(a==t&&b!=s){
          int fa=dsu.find(b);
          if(!dsu.same(a,b)&&!viss[fa]&&vist[fa]&&!vis[fa]){
            dsu.unite(a,b);
            ans.push_back(e[i]);
            d[a]++,d[b]++;
            vis[fa]=1;
          }
        }else if(b==t&&a!=s){
          int fa=dsu.find(a);
          if(!dsu.same(a,b)&&!viss[fa]&&vist[fa]&&!vis[fa]){
            dsu.unite(a,b);
            d[a]++,d[b]++;
            ans.push_back(e[i]);
            vis[fa]=1;
          }
        }
      }
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(a==s&&b==t) continue;
        if(a==t&&b==s) continue;
        if(!dsu.same(a,b)){
          if(a==s&&d[s]>=ds)continue;
          if(b==s&&d[s]>=ds)continue;
          if(a==t&&d[t]>=dt)continue;
          if(b==t&&d[t]>=dt)continue;
          dsu.unite(a,b);
          d[a]++;
          d[b]++;
          ans.push_back(e[i]);
        }
      }
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(!dsu.same(a,b)){
          dsu.unite(a,b);
          d[a]++;
          d[b]++;
          ans.push_back(e[i]);
        }
      }
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(!dsu.same(a,b)){
          cout<<"No";
          return 0;
        }
      }
      if(d[s]>ds||d[t]>dt)cout<<"No";
      else {
        cout<<"Yes"<<endl;
        for(auto p:ans)cout<<p.fi<<' '<<p.se<<endl;
      }
    }
    

    3.19/8/9

    #377Div2 [4/6]

    A.模拟情况 B.贪心,先优先变成偶数

    C.并查集,把一个集合都变成集合内数量最多的颜色

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define ll long long
    #define pii pair<int,int>
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=4e5+20,maxm=1e6+10;
    int casn,n,m,k;
    class ufs{public:
      int fa[maxn];
      void init(int n){rep(i,1,n) fa[i]=i;}
      int find(int now){return fa[now]==now?now:fa[now]=find(fa[now]);}
      void unite(int a,int b){
        int fx=find(a),fy=find(b);
        fa[fy]=fx;
      }
    }dsu;
    int c[maxn],vis[maxn];
    int mx[maxn];
    pii e[maxn];
    unordered_map<int,int> cnt[maxn];
    int main(){
      cin>>n>>m>>k;
      dsu.init(n);
      rep(i,1,n)cin>>c[i];
      rep(i,1,m){
        int a,b;cin>>a>>b;e[i]={a,b};
        dsu.unite(a,b);
      }
      rep(i,1,m){
        int a=e[i].fi,b=e[i].se;
        if(!vis[a])vis[a]=1,cnt[dsu.find(a)][c[a]]++;
        if(!vis[b])vis[b]=1,cnt[dsu.find(a)][c[b]]++;
      }
      rep(i,1,n){
        int mxx=0,mxid=c[i];
        for(auto j:cnt[i]) if(j.se>mxx) mxx=j.se,mxid=j.fi;
        mx[i]=mxid;
      }
      int ans=0;
      rep(i,1,n){
        if(c[i]!=mx[dsu.find(i)]) ans++;
      }
      cout<<ans<<endl;
    }
    

     F.前缀和乱搞

    #include <bits/stdc++.h>
    #define ll long long
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=2e5+20,maxm=1e6+10;
    int casn,n,m,k;
    ll dp[maxn];
    int main(){
      cin>>n;
      rep(i,1,n){
        cin>>k;dp[k]++;
      }
      rep(i,1,maxn-10) dp[i]+=dp[i-1];
      ll ans=0;
      rep(i,1,maxn-10) if(dp[i]!=dp[i-1]){
        ll tmp=0;
        for(int j=i;j<maxn-10;j+=i) tmp+=j*(dp[min(maxn-11,j+i-1)]-dp[j-1]);
        ans=max(tmp,ans);
      }
      cout<<ans;
    }
    

    2.19/8/8

    zoj 月赛18/1

    A.贪心即可 J.滑窗+记忆化

    E.线段树维护区间乘积,区间取幂,区间乘法,需要用费马大定理降幂

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;//head
    const int maxn=2e5+10,maxm=2e6+10;
    const ll INF=0x3f3f3f3f,mod=1e9+7;
    int casn,n,m,k;
    ll pow_mod(ll a,ll b,ll ans=1) {
      while(b) {
        if(b&1) (ans*=a)%=mod;
        (a*=a)%=mod,b>>=1;
      }
      return ans;
    }
    class segtree{public:
    #define nd node[now]
    #define ndl node[now<<1]
    #define ndr node[now<<1|1]
      struct segnode{int l,r;ll sum,pw,mul;}node[maxn<<2|3];
      inline void pushup(int now){nd.sum=ndl.sum*ndr.sum%mod;}
      inline void pushdown(int now){
        if(nd.pw>1){
          (ndl.pw*=nd.pw)%=mod-1;(ndr.pw*=nd.pw)%=mod-1;
          ndl.mul=pow_mod(ndl.mul,nd.pw);ndr.mul=pow_mod(ndr.mul,nd.pw);
          ndl.sum=pow_mod(ndl.sum,nd.pw);ndr.sum=pow_mod(ndr.sum,nd.pw);
          nd.pw=1;
        }
        if(nd.mul>1){
          (ndl.mul*=nd.mul)%=mod;(ndr.mul*=nd.mul)%=mod;
          (ndl.sum*=pow_mod(nd.mul,ndl.r-ndl.l+1))%=mod;
          (ndr.sum*=pow_mod(nd.mul,ndr.r-ndr.l+1))%=mod;
          nd.mul=1;
        }
      }
      void maketree(int s,int t,int now=1){
        nd={s,t,0,1,1};
        if(s==t){cin>>nd.sum;return ;}
        maketree(s,(s+t)>>1,now<<1);
        maketree(((s+t)>>1)+1,t,now<<1|1);
        pushup(now);
      }
      void mul(int s,int t,ll x,int now=1){
        if(s<=nd.l&&t>=nd.r){
          (nd.mul*=x)%=mod;
          (nd.sum*=pow_mod(x,nd.r-nd.l+1))%=mod;
          return ;
        }
        pushdown(now);
        if(s<=ndl.r) mul(s,t,x,now<<1);
        if(t>ndl.r) mul(s,t,x,now<<1|1);
        pushup(now);
      }
      void pow(int s,int t,ll x,int now=1){
        if(s<=nd.l&&nd.r<=t){
          (nd.pw*=x)%=mod-1;
          nd.sum=pow_mod(nd.sum,x);
          nd.mul=pow_mod(nd.mul,x);
          return ;
        }
        pushdown(now);
        if(s<=ndl.r) pow(s,t,x,now<<1);
        if(t>ndl.r) pow(s,t,x,now<<1|1);
        pushup(now);
      }
      ll query(int s,int t,int now=1){
        if(s<=nd.l&&t>=nd.r)return nd.sum;
        pushdown(now);
        ll sum=1;
        if(s<=ndl.r) sum=query(s,t,now<<1);
        if(t>ndl.r) (sum*=query(s,t,now<<1|1))%=mod;
        return sum;
      }
    }tree;
    ll read(ll ret=0){
      char ch=getchar();
      while(ch>'9'||ch<'0')ch=getchar();
      while(ch>='0'&&ch<='9'){
        ret=ret*10+ch-'0';ch=getchar();
      }return ret;
    }
    int main() {
      casn=read();
      while(casn--){
        n=read();m=read();
        tree.maketree(1,n);
        while(m--){
          int a=read(),b=read(),c=read();
          if(a==1) tree.mul(b,c,read());
          else if(a==2) tree.pow(b,c,read());
          else printf("%lld
    ",tree.query(b,c));
        }
      }
      return 0;
    }
    

    1.19/8/7

    #377Div2 [6/6]

    A.枚举数量  B.贪心满足 C.枚举情况 D.二分答案

    E.sort后从小到大贪心,u_map记录答案

    F.求出边双连通分量之后,从最大的边双作为根,bfs所有剩余点,最大的边双内部单独再dfs一下就行

    #include <bits/stdc++.h>
    #define endl '
    '
    #define fi first
    #define se second
    #define mp make_pair
    #define pii pair<int,int>
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=4e5+20,maxm=1e6+10;
    int casn,n,m,k;
    int stk[maxn],top,cnt,dfn[maxn],low[maxn],numc,belong[maxn],vis[maxn],sz[maxn];
    struct node {int to,next;}e[maxm];int head[maxn],nume;
    inline void add(int a,int b){e[++nume]=(node){b,head[a]};head[a]=nume;}
    void tdfs(int now,int pre){
      dfn[now]=low[now]=++cnt;
      stk[top++]=now,vis[now]=1;
      for(int i=head[now];i;i=e[i].next){
        int to=e[i].to;
        if(to==pre) continue;
        if(!dfn[to]){tdfs(to,now);low[now]=min(low[now],low[to]);}
        else low[now]=min(low[now],dfn[to]);
      }
      if(low[now]==dfn[now]){
        numc++;
        int to;
        do{to=stk[--top];
          belong[to]=numc;
          sz[numc]++;
        }while(to!=now);
      }
    }
    pii ge[maxn];
    map<pii,pii> ed;
    queue<int> que;
    void dfs(int now,int pre){
      if(vis[now]) return ;
      vis[now]=1;
      int bn=belong[now];
      for(int i=head[now];i;i=e[i].next){
        int to=e[i].to;
        if(belong[to]!=bn){
          que.push(to);
          vis[to]=1;
          pii x=mp(min(to,now),max(to,now));
          ed[x]=mp(to,now);
        }else {
          pii x=mp(min(to,now),max(to,now));
          if(ed.find(x)==ed.end()){
            ed[x]=mp(now,to);
          }
          dfs(to,now);
        }
      }
    }
    
    int main(){IO;
      cin>>n>>m;
      rep(i,1,m){
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
        if(a>b) swap(a,b);
        ge[i]={a,b};
      }
      for(int i=1;i<=n;i++) if(!dfn[i]) tdfs(i,i);
      int mxid=1;
      memset(vis,0,sizeof vis);
      rep(i,1,numc) if(sz[mxid]<sz[i])mxid=i;
      rep(i,1,n)if(belong[i]==mxid) {dfs(i,i);break;}
      while(!que.empty()){
        int now=que.front();que.pop();
        for(int i=head[now];i;i=e[i].next){
          int to=e[i].to;
          pii x=mp(min(to,now),max(to,now));
          if(belong[to]==mxid)continue;
          if(!vis[to]) {
            vis[to]=vis[now]+1;
            que.push(to);
          }
          if(vis[to]>vis[now])ed[x]={to,now};
          else ed[x]={now,to};
        }
      }
      cout<<sz[mxid]<<endl;
      rep(i,1,m) {
        pii x=ed[ge[i]];
        cout<<x.fi<<' '<<x.se<<endl;
      }
    }
    
  • 相关阅读:
    git常用命令总结
    chrome浏览器使用技巧
    chorme浏览器的Access-Control-Allow-Origin拦截限制
    基于HP DL388 Gen 9服务器基本配置(ESXI 6.5)
    c# winform 窗体之间的传参
    <<测试驱动开发的艺术>>读书笔记
    <<人性的弱点>>读书笔记
    一个很奇怪的重复链接lib的问题
    redis集群的一些笔记
    <<敏捷开发>>读书笔记
  • 原文地址:https://www.cnblogs.com/nervendnig/p/11318193.html
Copyright © 2020-2023  润新知