题目大意:
给定一个图
G=(V,E)
,将边分为
L
个集合,使得每个集合都是一个割集,求
分析:
由源点
s
做
证明:我们假设
L>dis[t]
,那么相当于把原图分成了大于
dis[t]
层,因此从
s
到
至于构造方法就很简单了,只要把满足
dis[v]=dis[u]+1
的边
(u,v)
计入集合
dis[v]
中,同时注意把
dis[v]≥dis[t]
的边特判一下即可。
AC code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define pb push_back
#define ONLINE_JUDGE
using namespace std;
const int MAXN = 409;
const int INF = 0x3f3f3f3f;
int n, m, s, t;
struct Net
{
int size;
int head[MAXN];
int to[MAXN*MAXN];
int ne[MAXN*MAXN];
Net(){size = 1;}
void add_edge(int u, int v)
{
to[size] = v, ne[size] = head[u], head[u] = size++;
to[size] = u, ne[size] = head[v], head[v] = size++;
}
}G;
int e[MAXN*MAXN][2];
int dis[MAXN];
bool in[MAXN];
vector<int> edge[MAXN];
void spfa(int s)
{
queue<int> q;
memset(dis, INF, sizeof(dis));
q.push(s), dis[s] = 0, in[s] = true;
while(!q.empty())
{
int u = q.front();
q.pop(), in[u] = false;
for(int i = G.head[u]; i; i = G.ne[i])
{
int v = G.to[i];
if(dis[v] > dis[u]+1)
{
dis[v] = dis[u]+1;
if(!in[v])
{
in[v] = true;
q.push(v);
}
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu213.in", "r", stdin);
freopen("sgu213.out", "w", stdout);
#endif
scanf("%d%d%d%d", &n, &m, &s, &t);
for(int i = 1; i <= m; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
G.add_edge(u, v);
e[i][0] = u, e[i][1] = v;
}
spfa(s);
for(int i = 1; i <= m; ++i)
{
int u = e[i][0], v = e[i][1];
if(dis[u] > dis[v]) swap(u, v);
if(dis[u] == dis[v]-1 && dis[v] <= dis[t])
edge[dis[v]].pb(i);
else edge[1].pb(i);
}
printf("%d\n", dis[t]-dis[s]);
for(int i = 1; i <= dis[t]; ++i)
{
int sz = edge[i].size();
printf("%d", sz);
sort(edge[i].begin(), edge[i].end());
for(int j = 0; j < sz; ++j)
printf(" %d", edge[i][j]);
puts("");
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}