Editorial for Du lịch


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

#include<iostream>
#include<algorithm>
#define fr(a,b,c) for (a=b;a<=c;a++)
#define maxm 22222
#define maxn 16016
using namespace std;

int n,m,b[maxm],c[maxm],a[maxm*2],p[maxn],d[maxn],sm,cnt,low[maxn],num[maxn];
int last,st[maxn],f[maxn],aa[maxm*2],pp[maxn],l[maxn],pl[maxn],rev[maxn],e[maxn];

void visit(int x)
{
    int i;
    num[x]=++cnt; low[x]=cnt; st[++last]=x;
    fr(i,p[x]+1,p[x+1])
      if (!d[a[i]])
      {
         if (num[a[i]]) low[x]=min(low[x],num[a[i]]);
         else 
         {
            visit(a[i]);
            low[x]=min(low[x],low[a[i]]);
         }
      }
    if (num[x]<=low[x])
    {
       sm++;
       do
       {
          i=st[last--]; d[i]=sm; 
       } while (i!=x);
    }
}

void go(int x)
{
    int i;
    fr(i,pp[x]+1,pp[x+1]) 
    {
       if (!e[aa[i]]) go(aa[i]);
       if (!f[aa[i]]) f[x]=0;
    }
    e[x]=1;
    if (f[x]<0) 
    {
       f[x]=1;
       fr(i,pl[x]+1,pl[x+1]) f[l[i]]=0;
    }
}

int main()
{
    int i,x,y;
    cin >> m >> n;
    fr(i,1,n*2)
      if (i<=n) rev[i]=i+n;
      else rev[i]=i-n;
    fr(i,1,m)
    {
       scanf("%d%d",&x,&y);
       if (x<0) x=n-x;
       if (y<0) y=n-y;
       b[i]=x; c[i]=y;
       p[rev[x]]++; p[rev[y]]++;
    }
    fr(i,2,n*2+1) p[i]+=p[i-1];
    fr(i,1,m)
    {
       a[p[rev[b[i]]]--]=c[i];
       a[p[rev[c[i]]]--]=b[i];
    }   
    //strongly-connected components
    fr(i,1,n*2)
      if (!d[i]) visit(i);
    //check condition + create opposite vertex
    fr(i,1,n)
      if (d[i]==d[i+n])
      {
         cout << "NO" << endl;
         return 0;
      }
      else
      {
         pl[d[i]]++; pl[d[i+n]]++;
      }
    fr(i,2,sm+1) pl[i]+=pl[i-1];
    fr(i,1,n)
    {
       l[pl[d[i]]--]=d[i+n];
       l[pl[d[i+n]]--]=d[i];
    }
    //union
    fr(i,1,m)
    {
       if (d[rev[b[i]]]!=d[c[i]]) pp[d[rev[b[i]]]]++;
       if (d[rev[c[i]]]!=d[b[i]]) pp[d[rev[c[i]]]]++;
    }
    fr(i,2,sm+1) pp[i]+=pp[i-1];
    fr(i,1,m)
    {
       if (d[rev[b[i]]]!=d[c[i]]) aa[pp[d[rev[b[i]]]]--]=d[c[i]];
       if (d[rev[c[i]]]!=d[b[i]]) aa[pp[d[rev[c[i]]]]--]=d[b[i]];
    }
    //topo + find result
    fr(i,1,sm) f[i]=-1;
    fr(i,1,sm)
       if (!e[i]) go(i);
    //output
    int sl=0;
    fr(i,1,n) sl+=f[d[i]];
    cout << "YES" << endl;
    cout << sl << endl;
    fr(i,1,n)
       if (f[d[i]]) cout << i << " ";
    cout << endl; 
    return 0;
}

Code mẫu của happyboy99x

#include<bits/stdc++.h>
using namespace std;

#define TR(v,i) for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
const int M = 8000, INF = 1e9;
int n, m, d[2*M], low[2*M], iscc[2*M], nscc, timed;
vector<int> g[2*M], scc[2*M], sg[2*M];
bool choosescc[2*M];

int getVertice(int u) {
    return (abs(u)-1) << 1 | (u < 0 ? 1 : 0);
}

void enter() {
    cin >> n >> m;
    for(int i = 0; i < n; ++i) {
        int u, v; cin >> u >> v;
        u = getVertice(u); v = getVertice(v);
        g[u ^ 1].push_back(v);
        g[v ^ 1].push_back(u);
    }
}

stack<int> st;
void dfs(int u) {
    st.push(u);
    low[u] = d[u] = timed++;
    TR(g[u], v) if(d[*v] == -1)
        dfs(*v), low[u] = min(low[u], low[*v]);
    else
        low[u] = min(low[u], d[*v]);
    if(low[u] == d[u]) {
        int v;
        do {
            v = st.top(); st.pop();
            iscc[v] = nscc;
            scc[nscc].push_back(v);
        } while (v != u);
        ++nscc;
    }
    d[u] = INF;
}

void makeSuperGraph() {
    for(int u = 0; u < 2*m; ++u)
        TR(g[u], v)
            sg[iscc[u]].push_back(iscc[*v]);
}

bool mayHasSolution() {
    for(int u = 0; u < m; ++u)
        if(iscc[u << 1] == iscc[u << 1 | 1])
            return false;
    return true;
}

void StrongConnectedComponent() {
    fill(d, d+2*m, -1);
    for(int u = 0; u < 2*m; ++u)
        if(d[u] == -1) dfs(u);
}

void trace() {
    fill(choosescc, choosescc + nscc, true);
    for(int i = 0; i < nscc; ++i) if(choosescc[i])
        TR(scc[i], u) choosescc[iscc[*u ^ 1]] = false;
    int res = 0;
    for(int u = 0; u < m; ++u) if(choosescc[iscc[u << 1]])
        ++res;
    cout << "YES\n" << res << '\n';
    for(int u = 0; u < m; ++u) if(choosescc[iscc[u << 1]])
        cout << u+1 << ' ';
    cout << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    enter();
    StrongConnectedComponent();
    if(mayHasSolution()) {
        makeSuperGraph();
        trace();
    } else cout << "NO\n";
    return 0;
}

Code mẫu của ladpro98

#include <bits/stdc++.h>
const int N = 50000;

using namespace std;
int lab[N], st[N], low[N], num[N], res[N];
vector<int> a[N], com[N];
bool was[N], val[N];
int n, m, gap, nn, cnt, top, scc, k;

void Enter() {
    scanf("%d %d\n", &m, &n);
    gap = n + 1; nn = n + gap;
    int i, v, u;
    for(i=1; i<=m; i++) {
        scanf("%d %d\n", &u, &v);
        a[-u + gap].push_back(v + gap);
        a[-v + gap].push_back(u + gap);
    }

}

void DFS(int u) {
    low[u] = num[u] = ++cnt;
    st[++top] = u;
    int i, v;
    for(i=0; i<a[u].size(); i++) {
        v = a[u][i];
        if (was[v]) continue;
        if (num[v] != 0)
            low[u] = min(low[u], num[v]);
        else {
            DFS(v);
            low[u] = min(low[u], low[v]);
        }
    }
    if (num[u] == low[u]) {
        scc++;
        do {
            v = st[top--];
            was[v] = true;
            lab[v] = scc;
            com[scc].push_back(v);
        } while (v != u);
    }
}

int main()
{
    Enter();
    int i, j, v; bool mustTrue;
    for(i=1; i<=nn; i++)
    if (num[i] == 0) DFS(i);
    for(i=1; i<=n; i++)
    if (lab[i + gap] == lab[-i + gap]) {
        printf("NO"); return 0;
    }
    for(i=scc; i; i--) {
        mustTrue = false;
        for(j=0; j<com[i].size(); j++)
        if (val[com[i][j]]) {mustTrue = true; break;}
        if (!mustTrue) {
            for(j=0; j<com[i].size(); j++) {
                v = com[i][j];
                v = -(v - gap) + gap;
                val[v] = true;
            }
        }
        else {
            for(j=0; j<com[i].size(); j++) {
                v = com[i][j];
                val[v] = true;
            }
        }
    }
    printf("YES\n");
    for(i=1; i<=n; i++)
    if (val[i + gap]) res[++k] = i;
    printf("%d\n", k);
    for(i=1; i<=k; i++) printf("%d ", res[i]);
    return 0;
}

Code mẫu của RR

{$R-,Q-}
uses math;
const
  FINP='';
  FOUT='';
  MAXN=20000;
  MAXM=16000;
type
  list=^node;
  node=record u:longint; next:list; end;
var
  hsize,sl,top,count,m,n:longint;
  free,tp,low,num:array[-MAXN..MAXN] of longint;
  choose,dd,stack,deg,h,hpos:array[1..MAXN*2] of longint;
  ke:array[-MAXN..MAXN] of list;
  ds,ke2:array[1..MAXN] of list;
procedure add(u:longint;var a:list); inline;
var
  p:list;
begin
  new(p); p^.u:=u;
  p^.next:=a; a:=p;
end;
procedure inp;
var
  f:text;
  i,u,v:longint;
  procedure finish; inline;
  begin
    close(f);
    assign(f,FOUT); rewrite(f);
    writeln(f,'NO');
    close(f);
    halt;
  end;
begin
  assign(f,FINP); reset(f);
  read(f,m,n);
  for i:=-n to n do ke[i]:=nil;
  for i:=1 to m do
    begin
      read(f,u,v);
      if u=-v then continue;
      if u=v then
        begin
          if u<0 then begin if choose[-u]=1 then finish; choose[-u]:=-1; end
          else begin if choose[u]=-1 then finish; choose[u]:=1; end;
          continue;
        end;
      add(v,ke[-u]);
      add(u,ke[-v]);
    end;
  close(f);
end;
procedure dfs1(u:longint); inline;
var
  v:longint;
  p:list;
begin
  inc(top); stack[top]:=u;
  inc(count); num[u]:=count; low[u]:=count;
  p:=ke[u];
  while p<>nil do
    begin
      v:=p^.u; p:=p^.next;
      if free[v]=1 then continue;
      if num[v]=0 then
        begin
          dfs1(v);
          low[u]:=min(low[u],low[v]);
        end
      else low[u]:=min(low[u],num[v]);
    end;
  if num[u]=low[u] then
    begin
      inc(sl);
      ds[sl]:=nil;
      repeat
        v:=stack[top]; dec(top);
        tp[v]:=sl;
        free[v]:=1;
        add(v,ds[sl]);
      until v=u;
    end;
end;
procedure swap(var a,b:longint); inline;
var
  temp:longint;
begin
  temp:=a; a:=b; b:=temp;
end;
procedure downHeap(i:longint); inline;
var
  j:longint;
begin
  j:=i shl 1;
  while (j<=hsize) do
    begin
      if (j<hsize) and (deg[h[j+1]]<deg[h[j]]) then inc(j);
      if (deg[h[j]]<deg[h[i]]) then
        begin
          swap(hpos[h[i]],hpos[h[j]]);
          swap(h[i],h[j]);
        end;
      i:=j; j:=i shl 1;
    end;
end;
procedure upHeap(i:longint); inline;
var
  j:longint;
begin
  j:=i shr 1;
  while (i>1) and (deg[h[i]]<deg[h[j]]) do
    begin
      swap(hpos[h[i]],hpos[h[j]]);
      swap(h[i],h[j]);
      i:=j; j:=i shr 1;
    end;
end;
procedure push(u:longint); inline;
begin
  inc(hsize); h[hsize]:=u; hpos[u]:=hsize;
  upHeap(hsize);
end;
procedure pop(var u:longint); inline;
begin
  u:=h[1]; hpos[u]:=0;
  swap(h[1],h[hsize]);
  hpos[h[1]]:=0;
  dec(hsize); downHeap(1);
end;
procedure dfs2(u:longint); inline;
var
  p:list;
  v:longint;
begin
  if dd[u]=1 then exit;
  p:=ke2[u]; dd[u]:=1;
  while p<>nil do
    begin
      v:=p^.u; p:=p^.next;
      if dd[v]=1 then continue;
      dfs2(v);
    end;
end;
procedure finish; inline;
var
  f:text;
begin
  assign(f,FOUT); rewrite(f);
  writeln(f,'NO');
  close(f);
  halt;
end;
procedure solve;
var
  i,u,v:longint;
  p,pp:list;
  f:text;
begin
  count:=0;
  {Xay dung cac thanh phan lien thong manh}
  for i:=-n to n do
  if i<>0 then
    if num[i]=0 then dfs1(i);
  {Neu co thanh phan lien thong chua ca dinh u va -u thi dung lai}
  for i:=1 to n do
    if tp[i]=tp[-i] then finish;
  {Tao do thi voi cac dinh la cac thanh phan lien thong manh}
  fillchar(dd,sizeof(dd),0);
  for i:=1 to sl do
    begin
      p:=ds[i];
      while p<>nil do
        begin
          u:=p^.u; p:=p^.next;
          pp:=ke[u];
          while pp<>nil do
            begin
              v:=pp^.u; pp:=pp^.next;
              if tp[v]=i then continue;
              add(i,ke2[tp[v]]);
              inc(deg[i]);
            end;
        end;
    end;
  {sort topo}
  hsize:=0;
  for i:=1 to sl do
    if dd[i]=0 then push(i);
  top:=0;
  while hsize>0 do
    begin
      pop(u);
      inc(top); stack[top]:=u;
      p:=ke2[u];
      while p<>nil do
        begin
          v:=p^.u; p:=p^.next;
          if dd[v]=1 then continue;
          dec(deg[v]);
          upHeap(hpos[v]);
        end;
    end;
  {Xu ly}
  for i:=1 to n do
    if choose[i]=1 then
      begin
        tp[i]:=1;
        for u:=-n to n do
        if tp[u]=tp[i] then
          begin
            if u<0 then choose[-u]:=-1
            else choose[u]:=1;
            dfs2(tp[-u]);
          end;
      end;
  for i:=1 to sl do
    begin
      u:=stack[i];
      if dd[u]=1 then continue;
      dd[u]:=1;
      p:=ds[u];
      while p<>nil do
        begin
          v:=p^.u; p:=p^.next;
          if v<0 then begin if choose[-v]=1 then finish; choose[-v]:=-1; end
          else begin if choose[v]=-1 then finish; choose[v]:=1; end;
          dfs2(tp[-v]);
        end;
    end;
  assign(f,FOUT); rewrite(f);
  for i:=1 to n do
    if choose[i]=0 then
      begin
        writeln(f,'NO');
        close(f);
        halt;
      end;
  sl:=0;
  for i:=1 to n do if choose[i]=1 then inc(sl);
  writeln(f,'YES');
  writeln(f,sl);
  for i:=1 to n do if choose[i]=1 then write(f,i,' ');
  close(f);
end;
begin
  inp;
  solve;
end.

Code mẫu của ll931110

//#pragma comment(linker, "/STACK:16777216")
#include <algorithm>
#include <bitset>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <stack>
#include <queue>
#include <vector>
#include <utility>
using namespace std;

int num[20010],low[20010],mark[20010],pos[20010],ou[20010],lab[20010];
bool exist[20010];
int m,n;
int cnt,com = 0;
bool choose[20010];
vector< pair<int,int> > edge;
vector<int> adj[20010],rev[20010],element[20010];
stack<int> s;
map< pair<int,int>,bool > mp;

void DFS(int u)
{
    num[u] = low[u] = ++cnt;  s.push(u);
    for (int i = 0; i < adj[u].size(); i++)
    {
        int v = adj[u][i];
        if (!exist[v]) continue;
        if (num[v] < 0)
        {
            DFS(v);  low[u] = min(low[u],low[v]);
        }
        else low[u] = min(low[u],num[v]);
    }
    if (low[u] == num[u])
    {
        while (1)
        {
            int x = s.top();  s.pop();  
            pos[x] = com;  element[com].push_back(x);  exist[x] = false;  if (x == u) break;
        }
        com++;
    }
}

void toposort()
{
    cnt = -1;
    queue<int> q;
    for (int i = 0; i < com; i++) if (!ou[i]) q.push(i);
    while (!q.empty())
    {
        int u = q.front();  q.pop();  lab[++cnt] = u;
        for (int i = 0; i < rev[u].size(); i++)
        {
            int v = rev[u][i];  ou[v]--;  if (!ou[v]) q.push(v);
        }
    }
}

void mark_false(int u)
{
    for (int i = 0; i < rev[u].size(); i++)
    {
        int v = rev[u][i];
        if (mark[v] < 0)
        {
            mark[v] = 0;  mark_false(v);
        }
    }
}

int main()
{
//    freopen("twosat.in","r",stdin);
//    freopen("twosat.ou","w",stdout);
    scanf("%d %d", &m, &n);
    for (int i = 0; i < m; i++)
    {
        int u,v;  scanf("%d %d", &u, &v);
        if (u > 0) u = 2 * (u - 1); else u = 2 * (-u - 1) + 1;
        if (v > 0) v = 2 * (v - 1); else v = 2 * (-v - 1) + 1;
        if ( (u ^ v) == 1) continue;
        edge.push_back(make_pair(u ^ 1,v));
        adj[u ^ 1].push_back(v);        
        edge.push_back(make_pair(v ^ 1,u));
        adj[v ^ 1].push_back(u);
    }    

    memset(num,-1,sizeof(num));
    cnt = -1;
    memset(exist,true,sizeof(exist));
    for (int i = 0; i < 2 * n; i++) if (num[i] < 0) DFS(i);

    for (int i = 0; i < n; i++) if (pos[2 * i] == pos[2 * i + 1])
    {
        printf("NO\n");  return 0;
    }

    for (int i = 0; i < com; i++) adj[i].clear();
    memset(ou,0,sizeof(ou));
    for (vector< pair<int,int> >::iterator it = edge.begin(); it != edge.end(); it++)
    {
        int u = pos[it->first],v = pos[it->second];
        if (u == v || mp[make_pair(u,v)]) continue;
        mp[make_pair(u,v)] = true;  
        ou[u]++;  adj[u].push_back(v);  rev[v].push_back(u);
    }
    toposort();

    memset(mark,-1,sizeof(mark));
    for (int i = 0; i < com; i++) if (mark[lab[i]] < 0)
    {
        mark[lab[i]] = 1;
        int first_element = element[lab[i]][0];
        int alter = pos[first_element ^ 1];
        mark[alter] = 0;  mark_false(alter);
    }

    memset(choose,false,sizeof(choose));
    for (int i = 0; i < com; i++) if (mark[i] > 0)
      for (int j = 0; j < element[i].size(); j++) if (element[i][j] % 2 == 0) choose[element[i][j]/2] = true;

    vector<int> ret;
    for (int i = 0; i < n; i++) if (choose[i]) ret.push_back(i + 1);
    printf("YES\n");
    printf("%d\n", ret.size());
    for (int i = 0; i < ret.size(); i++) printf("%d ", ret[i]);
}

Code mẫu của skyvn97

#include<cstdio>
#include<stack>
#include<vector>
#include<cstring>
#include<algorithm>
#define MAXN   8000
#define x   first
#define y   second
using namespace std;
typedef pair<int,int> ii;
stack<int> st;
//for the first graph
int m,n;
vector<int> g[2*MAXN+7];
int low[2*MAXN+7];
int num[2*MAXN+7];
int ncp[2*MAXN+7];
bool fre[2*MAXN+7];
int res[2*MAXN+7];
int time;
//for the second graph
int nc;
vector<int> h[2*MAXN+7];
vector<int> comp[2*MAXN+7];
int cnt;
int topo[2*MAXN+7];
bool vst[2*MAXN+7];
int mark[2*MAXN+7];
ii lst[2*MAXN+7];
void loadgraph_1st(void) {
    scanf("%d",&m);
    scanf("%d",&n);
    int i,u,v;
    for (i=1;i<=n;i=i+1) {
        g[i].clear();
        g[i+n].clear();
    }
    for (i=1;i<=m;i=i+1) {
        scanf("%d",&u);
        scanf("%d",&v);
        if (u>0 && v>0) {
            g[u+n].push_back(v);
            g[v+n].push_back(u);
        }
        if (u>0 && v<0) {
            v=-v;
            g[u+n].push_back(v+n);
            g[v].push_back(u);
        }
        if (u<0 && v>0) {
            u=-u;
            g[u].push_back(v);
            g[v+n].push_back(u+n);
        }
        if (u<0 && v<0) {
            u=-u;v=-v;
            g[u].push_back(v+n);
            g[v].push_back(u+n);
        }
    }
    memset(fre,true,sizeof fre);
    memset(low,0,sizeof low);
    memset(num,0,sizeof num);
    time=0;
    nc=0;
    while (!st.empty()) st.pop();
}
int min(const int &x,const int &y) {
    if (x<y) return (x); else return (y);
}
void visit_1st(const int &u) {
    int i,v;
    time++;
    num[u]=time;
    low[u]=num[u];
    st.push(u);
    for (i=0;i<g[u].size();i=i+1) {
        v=g[u][i];
        if (fre[v]) {
            if (num[v]>0) low[u]=min(low[u],num[v]);
            else {
                visit_1st(v);
                low[u]=min(low[u],low[v]);
            }
        }
    }
    if (low[u]==num[u]) {
        nc++;
        comp[nc].clear();
        do {
            v=st.top();st.pop();
            fre[v]=false;
            ncp[v]=nc;
            comp[nc].push_back(v);
        }
        while (v!=u);
    }
}
void tarjan(void) {
    int i;
    for (i=1;i<=2*n;i=i+1)
        if (num[i]==0) visit_1st(i);
    for (i=1;i<=n;i=i+1)
        if (ncp[i]==ncp[i+n]) {
            printf("NO");
            exit(0);
        }
}
void loadgraph_2nd(void) {
    int i,j;
    for (i=1;i<=nc;i=i+1) h[i].clear();
    for (i=1;i<=2*n;i=i+1)
        for (j=0;j<g[i].size();j=j+1)
            h[ncp[i]].push_back(ncp[g[i][j]]);
    cnt=nc;
    memset(vst,true,sizeof vst);
}
void visit_2nd(const int &u) {
    int i,v;
    for (i=0;i<h[u].size();i=i+1) {
        v=h[u][i];
        if (vst[v]) {
            vst[v]=false;
            visit_2nd(v);
        }
    }
    cnt--;
    topo[u]=cnt;
    lst[u]=ii(-topo[u],u);
}
void sort_topo(void) {
    int i,j,u,v;
    for (i=1;i<=nc;i=i+1)
        if (vst[i]) {
            vst[i]=false;
            visit_2nd(i);
        }
    memset(mark,-1,sizeof mark);
    sort(&lst[1],&lst[nc+1]);
    for (i=1;i<=nc;i=i+1) {
        u=lst[i].y;
        if (mark[u]>=0) continue;
        mark[u]=1;
        for (j=0;j<comp[u].size();j=j+1) {
            v=comp[u][j];
            if (v>n) mark[ncp[v-n]]=0;
            else mark[ncp[v+n]]=0;
        }
    }
}
void print(void) {
    int i,j;
    int nk=0;
    for (i=1;i<=2*n;i=i+1) res[i]=mark[ncp[i]];
    for (i=1;i<=n;i=i+1) nk+=res[i];
    printf("YES\n%d\n",nk);
    j=0;
    for (i=1;i<=n;i=i+1)
        if (res[i]==1) {
            printf("%d",i);
            j++;
            if (j<nk) printf(" ");
        }
    printf("\nSang thuc giac thay sao dep hon hom qua :D");
}
int main(void) {
    loadgraph_1st();
    tarjan();
    loadgraph_2nd();
    sort_topo();
    print();
    return 0;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.