3 3 5 1 2 2 3 3 1 1 5 1 5 1 5 4 4 5 1 2 2 3 3 4 4 1 1 5 1 5 1 5 1 5
1 5 0 0 0 0 No solution
题意:有n个点,每个点是一个村庄,每个村庄都有一个发电站,每个电站可以给它所在的村庄和它有边直接连接的所有村庄供电,现在选出一些电站,使每个村庄都能被供电且每个村庄只被一个电站供电。每个村庄的发电站都只能在1-d天内的一个子区间工作,需要安排它在哪几天来工作,且每个电站一旦工作结束就不能再次启动,即它工作的时间是连续的。方案可能有多组,输出任意一组即可,无解输出No solution
解题思路:舞蹈链精确覆盖,每个城市d天都要有电供应,可以想到将列分为n*d。每个城市选择开动发电厂的时间必须连续,可将其根据对应区间分为若干行。也就是枚举开发电厂的头尾。但如果这样直接DLX会可能出现某个发电厂选多次。可以多列出n列,表示选了该发电厂。那么求一次精确覆盖后就不会出现发电厂选多次的情况了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cctype>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
const int maxn = 500005;
int n, m, d, x, y, tot;
int mp[100][100];
int p[1090][3], u[100], v[100];
struct DLX
{
int L[maxn], R[maxn], U[maxn], D[maxn];
int row[maxn], col[maxn], sum[maxn], ans[maxn];
int n, m, num, cnt;
void add(int k, int l, int r, int u, int d, int x, int y)
{
L[k] = l; R[k] = r; U[k] = u;
D[k] = d; row[k] = x; col[k] = y;
}
void reset(int n, int m)
{
num = 0x7FFFFFF;
this->n = n; this->m = m;
for (int i = 0; i <= m; i++)
{
add(i, i - 1, i + 1, i, i, 0, i);
sum[i] = 0;
}
L[0] = m, R[m] = 0, cnt = m + 1;
}
void insert(int x, int y)
{
int temp = cnt - 1;
if (row[temp] != x)
{
add(cnt, cnt, cnt, U[y], y, x, y);
U[D[cnt]] = cnt; D[U[cnt]] = cnt;
}
else
{
add(cnt, temp, R[temp], U[y], y, x, y);
R[L[cnt]] = cnt; L[R[cnt]] = cnt;
U[D[cnt]] = cnt; D[U[cnt]] = cnt;
}
sum[y]++, cnt++;
}
void remove(int k)
{
R[L[k]] = R[k], L[R[k]] = L[k];
for (int i = D[k]; i != k; i = D[i])
for (int j = R[i]; j != i; j = R[j])
{
D[U[j]] = D[j];
U[D[j]] = U[j];
sum[col[j]]--;
}
}
void resume(int k)
{
R[L[k]] = k, L[R[k]] = k;
for (int i = D[k]; i != k; i = D[i])
for (int j = R[i]; j != i; j = R[j])
{
D[U[j]] = j;
U[D[j]] = j;
sum[col[j]]++;
}
}
bool dfs(int k)
{
if (!R[0]) { num = min(k, num); return true; }
int now = R[0];
for (int i = now; i != 0; i = R[i])
if (sum[now] > sum[i]) now = i;
remove(now);
for (int i = D[now]; i != now; i = D[i])
{
ans[k] = row[i];
for (int j = R[i]; j != i; j = R[j]) remove(col[j]);
if (dfs(k + 1)) return true;
for (int j = L[i]; j != i; j = L[j]) resume(col[j]);
}
resume(now);
return false;
}
void display(int k)
{
for (int i = 0; i < num; i++)
{
u[p[ans[i]][0]] = p[ans[i]][1];
v[p[ans[i]][0]] = p[ans[i]][2];
}
for (int i = 1; i <= k; i++) printf("%d %d\n", u[i], v[i]);
}
}dlx;
int main()
{
while (~scanf("%d%d%d", &n, &m, &d))
{
tot = 0;
dlx.reset(n*(d*(d + 1) / 2 + 1), n * d + n);
memset(mp, 0, sizeof mp);
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
mp[x][y] = mp[y][x] = 1;
}
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &x, &y);
tot++;
dlx.insert(tot, i);
p[tot][0] = i, p[tot][1] = p[tot][2] = 0;
for (int j = x; j <= y; j++)
{
for (int k = j; k <= y; k++)
{
tot++;
dlx.insert(tot, i);
p[tot][0] = i, p[tot][1] = j, p[tot][2] = k;
for (int o = j; o <= k; o++)
for (int pp = 1; pp<=n; pp++)
if(mp[i][pp]||i==pp) dlx.insert(tot, (pp - 1)*d + o + n);
}
}
}
if (dlx.dfs(0)) dlx.display(n);
else printf("No solution\n");
putchar(10);
}
return 0;
}