电子眼问题:利用非递归深度遍历,树形动态规划,解决N图N节点最小覆盖问题,O(n)时间

#include<fstream>

#include<math.h>

#include<iostream>

#define MAXNUM 100

using namespace std;

ifstream fin("input.txt");

//ofstream fout("output.txt");

int stack[MAXNUM];

int ptr[MAXNUM];

int index[MAXNUM];

int p1,p2;

int f[MAXNUM];

int g[MAXNUM];

int k[MAXNUM];

int map[MAXNUM];

bool tag[MAXNUM];

void dfs(int s){

int p,j,i;

memset(tag,false,sizeof(tag));

memset(stack,0,sizeof(stack));

stack[0] = s;

ptr[0] = 0;

tag[s] = true;

for(p=0;p>=0;){

i = stack[p];

if(ptr[p]<k[i]){

j = map[index[i]+ptr[p]];

ptr[p]++;//表示遍历过此节点

if(p==0||j!=stack[p-1]){//不是回边,无向图中有向树处理

if(tag[j]){//说明i和j是环上的一边

p1 = i;

p2 = j;

return;

}

p++;

stack[p] = j;

ptr[p] = 0;

tag[j] = true;

}

}else{

p--;

}

}

}

int workout(int s){

int p,j,i;

stack[0] = s;

ptr[0] = 0;

f[0] = 1;

g[0] = 0;

for(p=0;p>=0;){//栈底初始

i = stack[p];

if(ptr[p] < k[i]){//可以遍历节点

j = map[index[i]+ptr[p]];

ptr[p]++;

//去掉一条圈上的边形成一棵树,不需要标记了

if((i!=p1||j!=p2)&&(i!=p2||j!=p1)&&(p==0||j!=stack[p-1])){

p++;

f[p] = 1;

g[p] = 0;

stack[p] = j;

ptr[p] = 0;

}

}else//节点遍历完毕

{ //修改节点权

if(p>0){

f[p-1] += min(f[p],g[p]);

g[p-1] += f[p];

}

p--;//退栈

}

}

return f[0];

}

 

int main(){

int n,i,j;

int t=0;

fin>>n;

for(i=1;i<=n;i++){

index[i] = t;

fin>>k[i];

for(j=0;j<k[i];j++){

fin >> map[t++];

}

}

dfs(1);

cout<<min(workout(p1),workout(p2))<<endl;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值