210 UER 6 尋找罪犯

2021-07-14 08:02:50 字數 1585 閱讀 8098

開始就感覺是 二分圖

然後就棄t1後就一直想一直想

然而也沒想出來

暴力都沒法打啊......

題解確實是二分圖 演算法四的優化也是非常神!!! 神的到現在也沒看懂.....

60:

#include#include#include#include#includeusing namespace std;

const int n=800000;

struct h

e[n*2];

int first[n],dfn[n],low[n],stk[n],v[n],bl[n],d[n];

int top,num,tot,cnt,ti,p,q,n,m,x,y,z,ans[n],c[n];

vector>v[n];

vectore[n];

void add(int x,int y)

;    first[x]=tot;

if(tot&1) add(y^1,x^1);

}void dfs(int x)

else if(v[e[i].x])

low[x]=min(low[x],dfn[e[i].x]);

if(low[x]==dfn[x])

}void f()

for(int i=2;i<=cnt;i++) dfn[bl[i]]=i;

memset(v,0,sizeof(v));

for(int i=1;i<=num;i++)

if(!v[c[i]])

v[bl[dfn[c[i]]^1]]=1;

else

for(int j=0;j<(int)

e[c[p]].size();j++)

v[e[c[p]][j]]=1;

}int main()

for(int i=1;i<=n;i++)

if(v[i].size()) add(i*2,cnt-6);

}cnt--;

for(int i=2;i<=cnt;i++)

if(!dfn[i]) dfs(i);

for(int i=1;i<=n;i++)

if(bl[i*2]==bl[i*2+1])

for(int i=2;i<=cnt;i++)

for(int j=first[i];j;j=e[j].nex)

if(bl[e[j].x]!=bl[i])

e[bl[e[j].x]].push_back(bl[i]);

for(int i=1;i<=num;i++)

for(int i=1;i<=num;i++)

for(int j=0;j<(int)e[i].size();j++)

d[e[i][j]]++;

f();

for(int i=1;i<=n;i++)

if(v[bl[i*2]])

ans[++ans[0]]=i;

printf("%d\n",ans[0]);

for(int i=1;i<=ans[0];i++) printf("%d ",ans[i]);

return 0;

}

UOJ 210 UER 6 尋找罪犯

有n個人分為好人和壞人,說了m句話。好人不會說假話,壞人至多說一句謊話。求出一組解,滿足要求。利用2 sat拆點,乙個人拆成兩個點,表示他是好人和壞人。然而這樣的話邊數是m 2的,所以用前 字尾和優化構圖即可。1 include 2 using namespace std 34 const int ...

UER 2 謠言的傳播

寫了個亂搞,怎麼莫名其妙就ac了,這.之後又想了30min結合題解終於會證了。首先最大值比較簡單,記 f i 為第 i 個點能到達的點數,上界 sum n f i 一定可以取到。考慮取到是這麼一件事情,如果 b x y 那麼 y 一定不能是 x 在外向樹上的祖先以及環上的節點,外向樹的根的前驅例外。...

UER 2 資訊的交換

吉利題.不難發現,置換中的每乙個迴圈是獨立的,每乙個迴圈分別對應乙個獨立的聯通塊。根據題目的性質,每乙個聯通塊做的事情等價於其按照編號從小到大遍歷的的dfs生成樹做的事情,那麼只需要考慮一棵dfs生成樹做的事情即可。對於一棵dfs生成樹,將每個點的兒子按照編號從小到大排序,考慮節點 u 以及它的兒子...