题意:
1.每个城市都有一个发电站。
2.一个城市开始发电,直接相连接的城市也将有电。
3.一个城市只能得到来自一个发电站的电力供应。
4.发电站有一个工作范围,并且可选择这个范围的一个子区间
5.一个发电站一旦停止工作,不能重新启动。
6.每个时间每个城镇只能有一个供应者。
分析:
因为每个城市每一时间只能有一个供应者。所以将列选择为每个城市的每一天。所有就是精确覆盖问题了。数据范围较小,正好满足。因为也可以是子区间进行供电,所以行定义为每个发电站工作的子区间,注意到可能有些发电站不用使用,所以再定义一行只是区间范围是0-0的子区间,对应该发电站。
#include<bits/stdc++.h>
using namespace std;
const int maxn=20*60;
const int maxm=7*60;
const int maxnode=maxn*maxm;
struct DLX{
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[maxn],S[maxm];
int ansd,ans[maxnode];
void init(int _n,int _m){
n=_n;
m=_m;
for(int i=0;i<=m;i++){
S[i]=0;
U[i]=D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
R[m]=0;L[0]=m;
size=m;
for(int i=1;i<=n;i++){
H[i]=-1;
}
}
void Link(int r,int c){
++S[Col[++size]=c];
Row[size]=r;
D[size]=D[c];
U[D[c]]=size;
U[size]=c;
D[c]=size;
if(H[r]<0) H[r]=L[size]=R[size]=size;
else{
R[size]=R[H[r]];
L[R[H[r]]]=size;
L[size]=H[r];
R[H[r]]=size;
}
}
void remove(int c){
L[R[c]]=L[c];
R[L[c]]=R[c];
for(int i=D[c];i!=c;i=D[i]){
for(int j=R[i];j!=i;j=R[j]){
U[D[j]]=U[j];
D[U[j]]=D[j];
--S[Col[j]];
}
}
}
void resume(int c){
for(int i=U[c];i!=c;i=U[i]){
for(int j=L[i];j!=i;j=L[j]){
++S[Col[U[D[j]]=D[U[j]]=j]];
}
}
L[R[c]]=R[L[c]]=c;
}
bool dance(int d){
if(R[0]==0){
ansd=d;
return 1;
}
int c=R[0];
for(int i=R[0];i!=0;i=R[i]){
if(S[i]<S[c]){
c=i;
}
}
remove(c);
for(int i=D[c];i!=c;i=D[i]){
ans[d]=Row[i];
for(int j=R[i];j!=i;j=R[j]) remove(Col[j]);
if(dance(d+1)) return 1;
for(int j=L[i];j!=i;j=L[j]) resume(Col[j]);
}
resume(c);
return false;
}
}dlx;
int n,m,D;
bool g[maxn][maxm];
struct pow{
int s,e,index;
}p[maxn],tmp[maxnode];
void build(){
int cnt=1;
for(int i=1;i<=n;i++){
for(int j=p[i].s;j<=p[i].e;j++){ //1-j的时间段。
for(int k=p[i].s;k<=j;k++){ //1-j时间段的所有子区间k-j
dlx.Link(cnt,i);
tmp[cnt].s=k,tmp[cnt].e=j,tmp[cnt].index=i;
for(int r=1;r<=n;r++){
if(!g[i][r]) continue;
for(int d=k;d<=j;d++){ //在哪天。
dlx.Link(cnt,d*n+r);
}
}
cnt++;
}
}
dlx.Link(cnt,i); //多加的一行。
tmp[cnt].s=0,tmp[cnt].e=0,tmp[cnt].index=i;
cnt++;
}
}
int main(){
while(scanf("%d%d%d",&n,&m,&D)!=EOF){
dlx.init(16*n,n*D+n);
memset(g,0,sizeof g);
int a,b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
g[a][b]=g[b][a]=1;
}
for(int i=1;i<=n;i++){
scanf("%d%d",&a,&b);
g[i][i]=1;
p[i].s=a;p[i].e=b;
}
build();
if(!dlx.dance(0)){
printf("No solution\n");
}else{
memset(p,0,sizeof p);
for(int i=0;i<dlx.ansd;i++){
p[tmp[dlx.ans[i]].index].s=tmp[dlx.ans[i]].s;
p[tmp[dlx.ans[i]].index].e=tmp[dlx.ans[i]].e;
}
for(int i=1;i<=n;i++){
printf("%d %d\n",p[i].s,p[i].e);
}
}
printf("\n");
}
return 0;
}