题目
这题题目比较复杂,我就简述一下,系统中有n 个进程和由L-Z大写字母表示的资源,资源不接受并发访问,每个进程同时需要两个资源,由此可以构建等待链(等待链定义见原题),问如何安排每个进程的资源获取顺序,使得最长的等待链最小
分析
这题重要的是建模,把原问题转化为图模型,每个资源变为一个点,每个进程变为一条无向边连接着所需要的资源,那么安排等待资源顺序就相当于给无向边定向,例如进程1需要资源L和M才能运行,那么就有两种可能,第一种是先获取L,再获取M,定向后就是L->M,第二种是先获取M,再获取L,定向后就是M->L
然后我们的目标就转化为了n条边如何定向,才能使图中无环且最长路最短,图中有环就说明存在死锁,就是n个人做成一个环分n只筷子(筷子在环中的空格中),每个人手中都有一只(都先拿左筷子),不愿意放开,但是都需要两只筷子才能吃饭(少右筷子),吃完饭之后才能放下筷子,把筷子给别人用,这就是死锁
接下来将节点分层,分为p层,同层的节点之间无边相连,对于任意一条边,把它定向为层数小的节点指向层数大的节点,那么定向后图中肯定没有圈,而且最长路长度小于p,按照紫书上的解释,最长路长度正好等于p-1,所以求最小分层数量即可求解,最小分层数量等于图的点涂色的最少颜色数量
注意 这道题中判断点的子集是否是独立集这一步要预处理,这一步时间复杂度就会变为 ,否则在DP函数中调用判断是否是独立集的函数,这一步时间复杂度是 ,因为判断点涂色是 ,所以需要预处理,不然会超时
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
const int maxn=(1<<15),maxe=105,Inf=1000000000;
int n,u,v,S,d[maxn],son[maxn],independent[maxn],color[20];
char r1,r2;
pair<int,int> nodePair[maxe];
vector<int> edge;
bool edgeInside(int t){
for(int i=0;i<n;++i){
if((t|edge[i])==t) return true;
}
return false;
}
int DP(int nodes){
int &t=d[nodes];
if(t>=0) return t;
t=Inf;
for(int s=nodes;s;s=(s-1)&nodes){
if(independent[s]){
int temp=DP(nodes^s)+1;
if(temp<t){
t=temp;
son[nodes]=s; //记录最优的解
}
}
}
return t;
}
int main(void){
//n代表进程数(边数),m代表资源数(节点数)
while(cin>>n){
edge.clear();
S=0;
for(int i=0;i<n;++i){
scanf(" %c %c",&r1,&r2);
u=r1-'L';
v=r2-'L';
nodePair[i]=make_pair(u,v);
edge.push_back((1<<u)|(1<<v));
S|=(1<<u);
S|=(1<<v);
}
//枚举S的子集s
memset(d,-1,sizeof(d));
memset(son,-1,sizeof(son));
// memset(color,-1,sizeof(color));
memset(independent,0,sizeof(independent));
for(int s=S;s;s=(s-1)&S){ //对判断s是否是独立集的预处理,节省时间
independent[s]=(!edgeInside(s));
}
d[0]=0;
DP(S);
printf("%d\n",d[S]-2); //一开始就是两个颜色,所以要减去
for(int s=S,k=0;s;s=(s^son[s]),++k){
for(int i=0;i<15;++i){
if((son[s])&(1<<i)){
color[i]=k;
}
}
}
for(int i=0;i<n;++i){
pair<int,int> &tpair=nodePair[i];
if(color[tpair.first]<color[tpair.second]){
printf("%c %c\n",tpair.first+'L',tpair.second+'L');
}else{
printf("%c %c\n",tpair.second+'L',tpair.first+'L');
}
}
}
return 0;
}