zoukankan      html  css  js  c++  java
  • 1891: 丘比特的烦恼

    Description

    随着社会的不断发展,人与人之间的感情越来越功利化。最近,爱神丘比特发现,爱情也已不再是完全纯洁的了。这使得丘比特很是苦恼,他越来越难找到合适的男女,并向他们射去丘比特之箭。于是丘比特千里迢迢远赴中国,找到了掌管东方人爱情的神——月下老人,向他求教。月下老人告诉丘比特,纯洁的爱情并不是不存在,而是他没有找到。在东方,人们讲究的是缘分。月下老人只要做一男一女两个泥人,在他们之间连上一条红线,那么它们所代表的人就会相爱——无论他们身处何地。而丘比特的爱情之箭只能射中两个距离相当近的人,选择的范围自然就小了很多,不能找到真正的有缘人。丘比特听了月下老人的解释,茅塞顿开,回去之后用了人间的最新科技改造了自己的弓箭,使得丘比特之箭的射程大大增加。这样,射中有缘人的机会也增加了不少。情人节(Valentine's day)的午夜零时,丘比特开始了自己的工作。他选择了男女各N位,感应到他们互相之间是否有缘分。稍稍思考后,他发现恰好可以发现射出N支神箭,使每个人都找到自己的有缘人。正当他为自己的发现兴奋不已,准备射箭时,突然想到,自己只感应了是否有缘分,而没考虑缘分的大小。若是拘泥于射N支神箭,却使得某些有天地良缘的不能终成眷属,或勉强把某些只有猿粪的男女撮合在一起,便不合自己的本意了。但是,把每对男女再感应一次太耗时间,于是丘比特只好求助于你了。 Your Task 告诉你他们之间的缘分,请你找出,在射出N支神箭的前提下,哪些对有缘人一定会在一起,而哪些对有缘人一定会分开。

    Input

    第一行N M,表示人数与有缘人的对数接下来M行,每行X Y表示第X个男子与第Y个女子有缘分 N<=200000,M<=600000

    Output

    按输入顺序,对于每对有缘人输出一个数若该对有缘人一定在一起则输出1,若一定分开输出2,否则输出0

    Sample Input

    3 6

    1 1

    2 2

    3 3

    1 2

    2 1

    3 1

    Sample Output

    001002

    题解:http://blog.csdn.net/pouy94/article/details/6423218

    打了好久,终于打出来了

    首先我们要求出这个题的一个完备匹配,然后再做第二问(第二问的做法请见bzoj2140: 稳定婚姻

    现在就是要做第一问,n<=200000,m<=600000丧心病狂

    但是还是可以做的,因为匈牙利是有优化的就是像dinic一样(虽然我没打过)先标距离标号,然后多路增广,增广时只走标号加1的点(每次多路增广前清空vis数组,多路增广时vis数组不要清空,要不然就不是多路增广,一开始我就错这里了,结果第一个点就超时,不要问我为什么知道,我是不会告诉你我为了测试这个把输出故意搞错,就是一定WA的那种)

      1 const
      2     maxn=200200;
      3     maxm=600600;
      4 var
      5     d,first,flag,a:array[0..maxn*2]of longint;
      6     last,next,ans:array[0..maxm*2]of longint;
      7     n,m,p,tot,time:longint;
      8 
      9 procedure insert(x,y:longint);
     10 begin
     11     inc(tot);
     12     last[tot]:=y;
     13     next[tot]:=first[x];
     14     first[x]:=tot;
     15 end;
     16 
     17 function find(x:longint):boolean;
     18 var
     19     i:longint;
     20 begin
     21     i:=first[x];
     22     while i<>0 do
     23       begin
     24         if (flag[last[i]]<>time) and (d[x]+1=d[last[i]]) then
     25         begin
     26           flag[last[i]]:=time;
     27           if (a[last[i]]=0) or (find(a[last[i]])) then
     28           begin
     29             a[last[i]]:=x;
     30             a[x]:=last[i];
     31             exit(true);
     32           end;
     33         end;
     34         i:=next[i];
     35       end;
     36     exit(false);
     37 end;
     38 
     39 var
     40     q:array[0..maxn*2]of longint;
     41 
     42 procedure spfa;
     43 var
     44     i,l,r:longint;
     45 begin
     46     l:=1;
     47     r:=0;
     48     for i:=1 to 2*n do
     49       d[i]:=-1;
     50     for i:=1 to n do
     51       if a[i]=0 then
     52       begin
     53         inc(r);
     54         q[r]:=i;
     55         d[i]:=0;
     56       end;
     57     while l<=r do
     58       begin
     59         if q[l]<=n then
     60           begin
     61             i:=first[q[l]];
     62             while i<>0 do
     63               begin
     64                 if d[last[i]]=-1 then
     65                 begin
     66                   d[last[i]]:=d[q[l]]+1;
     67                   if a[last[i]]>0 then
     68                   begin
     69                     inc(r);
     70                     q[r]:=last[i];
     71                   end;
     72                 end;
     73                 i:=next[i];
     74               end;
     75           end
     76         else
     77           begin
     78             inc(r);
     79             q[r]:=a[q[l]];
     80             d[a[q[l]]]:=d[q[l]]+1;
     81           end;
     82         inc(l);
     83       end;
     84 end;
     85 
     86 procedure init;
     87 var
     88     i,x,y:longint;
     89 begin
     90     read(n,m);
     91     for i:=1 to m do
     92       begin
     93         read(x,y);
     94         insert(x,y+n);
     95         insert(y+n,x);
     96       end;
     97     while p<n do
     98       begin
     99         spfa;
    100         inc(time);
    101         for i:=1 to n do
    102           if a[i]=0 then
    103           if find(i) then inc(p);
    104       end;
    105 end;
    106 
    107 var
    108     dfn,low,c,s:array[0..maxn*2]of longint;
    109     cnt,t:longint;
    110 
    111 function min(x,y:longint):longint;
    112 begin
    113     if x<y then exit(x);
    114     exit(y);
    115 end;
    116 
    117 procedure dfs(x:longint);
    118 var
    119     i:longint;
    120 begin
    121     inc(t);
    122     dfn[x]:=t;
    123     low[x]:=t;
    124     flag[x]:=time;
    125     inc(tot);
    126     s[tot]:=x;
    127     i:=first[x];
    128     while i<>0 do
    129       begin
    130         if (a[x]=last[i]) xor (x>n) then
    131         begin
    132           if dfn[last[i]]=0 then
    133             begin
    134               dfs(last[i]);
    135               low[x]:=min(low[x],low[last[i]]);
    136             end
    137           else
    138             if flag[last[i]]=time then low[x]:=min(low[x],low[last[i]]);
    139         end;
    140         i:=next[i];
    141       end;
    142     if dfn[x]=low[x] then
    143     begin
    144       inc(cnt);
    145       while s[tot+1]<>x do
    146         begin
    147           flag[s[tot]]:=time-1;
    148           c[s[tot]]:=cnt;
    149           dec(tot);
    150         end;
    151     end;
    152 end;
    153 
    154 procedure tarjan;
    155 var
    156     i:longint;
    157 begin
    158     for i:=1 to n do
    159       if dfn[i]=0 then
    160       begin
    161         inc(time);
    162         t:=0;
    163         tot:=0;
    164         dfs(i);
    165       end;
    166 end;
    167 
    168 procedure print;
    169 var
    170     i,j:longint;
    171 begin
    172     for i:=1 to n do
    173       begin
    174         j:=first[i];
    175         while j<>0 do
    176           begin
    177             if c[i]<>c[last[j]] then
    178             begin
    179               if a[i]=last[j] then ans[(j+1)>>1]:=1
    180               else ans[(j+1)>>1]:=2;
    181             end;
    182             j:=next[j];
    183           end;
    184       end;
    185     for i:=1 to m do
    186       write(ans[i]);
    187 end;
    188 
    189 begin
    190     init;
    191     tarjan;
    192     print;
    193 end.
    View Code
  • 相关阅读:
    Linux改主机名最简单方法
    while 循环
    Appium UI自动化的那些梗
    常量函数、常量引用参数、常量引用返回值[C++]
    常量指针和指针常量的区别
    XHProf中文手册
    xhprof学习笔记
    C语言中内存操作函数
    DRF源码剖析——视图
    2020CCPC秦皇岛 k Kingdom’s Power
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3756104.html
Copyright © 2011-2022 走看看