P2860 [USACO06JAN]冗餘路徑Redundant Paths+tarjan算法+構建全環圖

題目大意:
任意兩個點之間至少有兩條邊相連,且兩條邊沒有重合之處。
例如:
1->2->3->4;
1->2->5->4;
不滿足要求;兩條路徑中都有1->2;
解題思路:
環中的任意兩點有兩條滿足要求的路徑;
在所給圖上添加邊,使得圖中任意一個點都在某個環中;
算法:
tarjan算法縮點+無向圖中統計入度和出度同時爲1的點的個數c+處理c;
**若c是偶數,則ans=c/2;若c是奇數,則ans=c/2+1;
處理c的方法,可以畫個圖看一下;

《就本題而言,Tarjan算法不受重邊的影響》

代碼中有許多細節需要注意:
1,因爲是無向圖且有環,對兩條邊同時進行標記,這就要使得控制e的cnt初始值爲-12,如果要使用兩次e數組和head數組,head數組要初始化,控制e數組的cnt要初始化-1,和第一次
相同;
#include<map>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int num=5010;
/*------------------*/
struct node{
    int u,v,next;
    bool flag;
}e[num<<2],e2[num<<2];

int head[num],cnt,cnt1;
int ip[num],op[num];
/*------------------*/
int dfn[num],low[num],ind,stack[num],t,cnt2,f[num];
bool vis[num];
/*------------------*/
/*------------------*/
/*------------------*/
int n,m;
void int_i(void)
{
    cnt=-1;
    memset(head,-1,sizeof(head));
    ind=0;
    t=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,-1,sizeof(low));
    memset(vis,0,sizeof(vis));
    memset(ip,0,sizeof(ip));
    memset(op,0,sizeof(op));
    cnt2=0;
    return ;
}
void addedge(int u,int v)
{
    e[++cnt].u=u;
    e[cnt].v=v;
    e[cnt].flag=false;
    e[cnt].next=head[u];
    head[u]=cnt;
    return ;
}
void addedge2(int u,int v)
{
    e2[++cnt].u=u;
    e2[cnt].v=v; 
    e2[cnt].next=head[u];
    head[u]=cnt;
    return ;
}
void tarjan(int u)
{
    int v;
    dfn[u]=low[u]=++ind;
    stack[++t]=u;
    vis[u]=true;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
       // printf("u===%d\n",u);
        if(e[i].flag) continue;
        e[i].flag=e[i^1].flag=true;
        v=e[i].v;
      //  printf("v==%d\n",v);
       // getchar();
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(vis[v])
        {
            low[u]=min(low[u],dfn[v]);
        }
    }

    if(dfn[u]==low[u])
    {
        cnt2++;
        do{
            v=stack[t--];
            vis[v]=false;
            f[v]=cnt2;
            //w[cnt2]++;
            //printf("%d,%d\n",cnt2,v);
        }while(v!=u);
    }
    return ;
}
int main()
{
    int u,v;
    scanf("%d%d",&n,&m);
    int_i();
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v);
		addedge(v,u);
    }
    tarjan(1);
    cnt1=cnt;
    cnt=0;
     //如果使用e數組進行下面的操作,那麼
 	//爲了保證數據的正確性,cnt應該和上面的初始條件相同==-1;
 	//如果此時cnt=0;那麼下面的循環,if語句裏的addedge的第一個,會覆蓋原始的數據
    memset(head,0,sizeof(head));
    for(int i=0;i<=cnt1;i++)
    {
        u=e[i].u;
        v=e[i].v;
        if(f[u]!=f[v])
        {
        	u=f[u];v=f[v];
            //printf("u==%d,v==%d\n",u,v);
            addedge2(u,v);
            op[u]++;ip[v]++;
        }
    }
    
    int c=0;
    for(int i=1;i<=cnt2;i++)
    {
        if(ip[i]==1&&op[i]==1){
            c++;
           // printf("i==%d\n",i);
        }
    }
    //!!!!!!!!!!!!!
    //每倆個點相連,奇數個點會剩餘1個; 
    if(c%2==1) c=c/2+1;
    else c=c/2;
    printf("%d\n",c);
    return 0;
}
/*
 7 7
 1 2
 2 3
 3 4
 2 5
 4 5
 5 6
 5 7
 */ 
 /*
 //第二個測試點的數據:
 200 250
1 3
106 1
134 1
157 134
23 106
60 134
44 60
117 1
126 1
11 134
139 44
178 3
97 60
101 157
118 44
30 23
128 30
174 3
108 23
110 128
132 157
92 106
173 132
79 106
82 178
7 44
52 79
74 30
4 23
49 7
164 139
127 30
156 4
65 7
120 101
46 97
112 178
8 46
59 60
198 174
100 134
90 92
192 60
125 100
26 178
19 192
63 125
155 126
70 100
35 63
151 126
165 157
146 70
84 157
141 52
160 70
163 8
38 127
171 139
62 101
133 11
177 146
158 125
41 165
145 52
98 30
5 177
68 164
168 173
107 178
86 132
199 127
136 168
71 155
50 128
189 35
193 46
105 70
195 189
89 158
69 177
190 50
28 19
21 92
93 71
170 86
122 21
131 136
197 158
16 108
33 195
18 164
196 141
94 92
61 79
149 26
169 193
124 163
78 189
147 108
150 49
129 70
77 168
194 18
54 100
140 127
24 196
109 158
2 97
17 195
64 28
115 174
185 41
81 141
45 62
180 18
167 109
27 65
123 140
188 77
91 129
73 110
76 173
14 149
103 105
51 11
57 84
58 101
148 193
43 156
162 109
22 61
179 52
67 74
200 117
6 167
119 192
113 41
184 16
32 98
39 160
75 32
175 98
121 78
183 26
47 174
102 79
83 23
172 127
176 74
138 121
182 90
29 156
153 183
114 162
152 47
15 136
12 64
143 155
161 89
99 90
87 114
25 193
144 86
137 64
135 52
56 14
55 112
20 71
142 5
34 126
116 56
40 79
130 89
187 49
85 62
111 136
191 39
166 16
159 120
13 50
95 55
154 33
96 171
181 115
88 21
80 24
48 14
72 21
31 67
9 31
66 143
37 117
104 56
36 86
42 125
186 33
10 184
53 18
164 64
136 63
77 25
128 105
133 147
130 1
67 161
10 132
190 173
195 80
123 1
70 82
126 38
163 7
193 17
152 105
44 24
168 185
174 163
177 40
79 173
70 19
26 60
198 130
97 22
143 67
97 25
119 89
194 163
188 180
49 173
109 71
4 124
58 79
151 178
74 93
34 96
161 65
167 16
172 114
183 14
46 116
199 187
118 175
109 23
101 115
160 114
110 173
96 28
77 182
27 116
 */ 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章