您的位置:首页 > 其它

NOIPの模拟_2016_7_20_t2_Graph Coloring

2016-07-20 19:47 274 查看
Description

现在你有一张无向图包含n个节点m条边。最初,每一条边都是蓝色或者红色。每一次你可以将一个节点连接的所有边变色(从红变蓝,蓝变红)。

找到一种步数最小的方案,使得所有边的颜色相同。

Input

第一行包含两个数n,m(1<=n,m<=100000)分别代表节点数和边的数量

接下来m行描述边,第i行ui,vi,ci,代表ui有一条颜色为ci的边与vi相连(ci是B或者是R),B代表蓝色,R代表红色。数据保证没有自环的边。

Output

如果没有方案就输出-1。否则第一行输出k代表最小的步数

Sample Input

输入1:

3 3

1 2 B

3 1 R

3 2 B

输入2:

3 3

1 2 B

3 1 R

3 2 B

输入3:

4 5

1 2 R

1 3 R

2 3 B

3 4 B

1 4 B

Sample Output

输出1:

1

输出2:

2

输出3:

-1

Data Constraint

对于30%数据,n<=20,m<=20

题目の大意:

给你一堆点,还有一堆边,每条边上有一个“R”或者“B”每一次可以把与一个点相邻的边全部换一种颜色(红变蓝蓝变红~)求最少的步数

比赛时の想法:

首先观摩一下数据の规模,105级别,于是就开始想nlogn的做法想着想着发现每一个点最多只会按一次,这是十分显然的,因为按两次对答案的贡献就为零了,于是在这个基础上继续想,然后我就发现如果边的目标颜色以及当前颜色确定,而且有一边的颜色确定,那么另外一边的颜色也是确定的。当时就想着可以分颜色选什么和第一个点取不取4种情况讨论,但是这个想法很好显然是错误的 233333333333

解法:

在前面想法的基础上,我们可以发现那个图不一定是一个联通图,ta可能是由多个块组成的,那么我们可以先做一次bfs分块,然后分全部染成红色和全部染成蓝色两种情况讨论,由与每个块都是相对独立的,于是我们可以对每个块分开讨论,对于每个块我们也是分成第一个点取或不取讨论,然后把对于每一个块取或不取的较小的答案加起来,然后把染成红色和染成蓝色需要的步数比较一下,输出较小的那个就可以了。注意如果在做某一个块时出现了不合法的情况,那么后面的块都不用做了,对于这个目标颜色所需“步数”为-1。

吐槽

哈哈哈哈又到了吐槽的时间啦,因为我太垃圾了,所以打的代码也很捞,别人2000byte的代码量被我强行打到6500byte,结果超级难调,看来要早日皈依C++了红红火火恍恍惚惚。

代码

稍微看一下就可以理解的超好超级垃圾的代码233

var
a,b:array[0..200005,1..2]of longint;
color:array[0..200005]of char;
bb,bz:array[0..100005]of boolean;
cc,skt,h:array[0..100005]of longint;
i,j,k,l,m,n,ans,tot,kk,ans1,ans2:longint;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2,1];
repeat
while a[i,1]<mid do inc(i);
while a[j,1]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
color[0]:=color[i];
color[i]:=color[j];
color[j]:=color[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure getred(zz:longint;ppp:boolean);
var
i,j,k,x,y:longint;
xx:boolean;
begin
skt[0]:=0;
tot:=0;
if ppp=true then
begin
tot:=1;
inc(skt[0]);
skt[skt[0]]:=zz;
end;
i:=1;
h[1]:=zz;
bz[zz]:=true;
j:=0;
xx:=false;
while j<i do
begin
if xx=true then break;
inc(j);
x:=h[j];
for k:=b[x,1] to b[x,2] do
if k>0 then
begin
y:=a[k,2];
if bz[y]=true then
begin
if (color[k]='R') and (bb[x]<>bb[y]) then
begin
xx:=true;
tot:=-1;
break;
end else
if (color[k]='B') and (bb[x]=bb[y]) then
begin
xx:=true;
tot:=-1;
break;
end;
end else
begin
bz[y]:=true;
if color[k]='R' then
begin
if bb[x]=false then bb[y]:=false else
begin
bb[y]:=true;
inc(tot);
inc(skt[0]);
skt[skt[0]]:=y;
end;
end else
begin
if bb[x]=false then
begin
bb[y]:=true;
inc(tot);
inc(skt[0]);
skt[skt[0]]:=y;
end else bb[y]:=false;
end;
inc(i);
h[i]:=y;
end;
end;
end;
if (tot<ans) and (tot<>-1) then ans:=tot;
for j:=1 to i do bz[h[j]]:=false;
for j:=1 to skt[0] do bb[skt[j]]:=false;
end;
procedure init;
begin
readln(n,m);
for i:=1 to m do
begin
readln(a[i,1],a[i,2],color[i],color[i]);
a[m+i,1]:=a[i,2];
a[m+i,2]:=a[i,1];
color[m+i]:=color[i];
end;
m:=m*2;
qsort(1,m);
b[a[1,1],1]:=1;
for i:=2 to m do
if a[i,1]<>a[i-1,1] then
begin
b[a[i-1,1],2]:=i-1;
b[a[i,1],1]:=i;
end;
b[a[m,1],2]:=m;
end;
procedure getblue(zz:longint;ppp:boolean);
var
i,j,k,x,y:longint;
xx:boolean;
begin
skt[0]:=0;
tot:=0;
if ppp=true then
begin
tot:=1;
inc(skt[0]);
skt[skt[0]]:=zz;
end;
i:=1;
h[1]:=zz;
bz[zz]:=true;
j:=0;
xx:=false;
while j<i do
begin
if xx=true then break;
inc(j);
x:=h[j];
for k:=b[x,1] to b[x,2] do
if k>0 then
begin
y:=a[k,2];
if bz[y]=true then
begin
if (color[k]='B') and (bb[x]<>bb[y]) then
begin
xx:=true;
tot:=-1;
break;
end else
if (color[k]='R') and (bb[x]=bb[y]) then
begin
xx:=true;
tot:=-1;
break;
end;
end else
begin
bz[y]:=true;
if color[k]='B' then
begin
if bb[x]=false then bb[y]:=false else
begin
bb[y]:=true;
inc(tot);
inc(skt[0]);
skt[skt[0]]:=y;
end;
end else
begin
if bb[x]=false then
begin
bb[y]:=true;
inc(tot);
inc(skt[0]);
skt[skt[0]]:=y;
end else bb[y]:=false;
end;
inc(i);
h[i]:=y;
end;
end;
end;
if (tot<ans) and (tot<>-1) then ans:=tot;
for j:=1 to i do bz[h[j]]:=false;
for j:=1 to skt[0] do bb[skt[j]]:=false;
end;
procedure bfs(x:longint);
var
i,j:longint;
q:array[0..100005]of longint;
begin
i:=1;
j:=0;
fillchar(q,sizeof(q),0);
q[1]:=x;
inc(k);
//  cc[x]:=k;
while j<i do
begin
inc(j);
for l:=b[q[j],1] to b[q[j],2] do
if bb[a[l,2]]=false then
begin
//  cc[a[l,2]]:=k;
inc(i);
q[i]:=a[l,2];
bb[a[l,2]]:=true;
end;
end;
end;
procedure de;
begin
k:=0;
for i:=1 to n do
if bb[i]=false then
begin
bfs(i);
cc[k]:=i;
end;
fillchar(bb,sizeof(bb),false);
end;
begin
//  assign(input,'2.in'); reset(input);
init;
de;
kk:=k;
for i:=1 to kk do
begin
// fillchar(bb,sizeof(bb),false);
bb[cc[i]]:=true;
ans:=maxlongint;
getred(cc[i],true);
// fillchar(bb,sizeof(bb),false);
getred(cc[i],false);
if ans=maxlongint then ans:=-1;
if ans=-1 then
begin
ans1:=-1;
break;
end;
ans1:=ans1+ans;
end;
for i:=1 to kk do
begin
//  fillchar(bb,sizeof(bb),false);
bb[cc[i]]:=true;
ans:=maxlongint;
getblue(cc[i],true);
// fillchar(bb,sizeof(bb),false);
getblue(cc[i],false);
if ans=maxlongint then ans:=-1;
if ans=-1 then
begin
ans2:=-1;
break;
end;
ans2:=ans2+ans;
end;
if ans1=-1 then
begin
if ans2=-1 then writeln(-1) else writeln(ans2);
end else
begin
if ans2=-1 then writeln(ans1) else
begin
if ans2>ans1 then writeln(ans1) else writeln(ans2);
end;
end;
//  close(input);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: