【无向图找环】网格树

题目

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
const int maxn = 2e5 + 5;
const int inf = 1e9 + 5;

using namespace std;

int n, m;
//int pre[maxn];
int a[30][30], b[30][30];

int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};

bool hascycle;
bool vis[30][30];
int ind[30][30];

void dfs(int x, int y, int px, int py){//dfs找无向图的环:记录前驱结点,若后继结点已经访问过且不是前驱结点,说明找到了环
	if(hascycle) return;
// 	if(x < 0 || x > n - 1 || y < 0 || y > m - 1 || a[x][y] == 0) return;

	for(int i = 0; i < 4; i++){
		int mx = x + dx[i], my = y + dy[i];
        if(mx < 0 || mx > n - 1 || my < 0 || my > m - 1 || a[mx][my] == 0) continue;//是mx不是x!!!!!!!
        // if(x < 0 || x > n - 1 || y < 0 || y > m - 1 || a[x][y] == 0) continue;
        if(vis[mx][my]){
            if(mx == px && my == py) continue;
            else{
                hascycle = 1;
                return;
            }
        }
        vis[mx][my] = 1;
		dfs(mx, my, x, y);
	}
}

// bool hascycle(){//拓扑排序找环:入度小于等于1的结点入队,遍历相邻结点,使其入度减1,若减完入度小于等于1,则入队。
                    //得用vis判断结点是否已经入过队,不然会死循环!!!!!!!!!!!!!!
// 	queue<pair<int, int>> q;
// 	int cnt = 0;
// 	bool vis[30][30] = {0};
// 	for(int i = 0; i < n; i++){
// 		for(int j = 0; j < m; j++){
// 			if(a[i][j] == 1 && ind[i][j] <= 1){
// 				q.push({i, j});
// 				cnt++;
// 				vis[i][j] = 1;
// 			}
// 		}
// 	}
// 	while(!q.empty()){
// 		auto u = q.front();
// 		q.pop();
// 		int x = u.first, y = u.second;
// 		for(int i = 0; i < 4; i++){
// 			int mx = x + dx[i], my = y + dy[i];
// 			if(mx < 0 || mx > n - 1 || my < 0 || my > m - 1 || a[mx][my] == 0) continue;
// 			ind[mx][my]--;
// 			if(ind[mx][my] <= 1 && !vis[mx][my]){
// 				q.push({mx, my});
// 				vis[mx][my] = 1;
// 				cnt++;
// 			}
// 		}
// 	}
// 	int tot = 0;
// 	for(int i = 0; i < n; i++){
// 		for(int j = 0; j < m; j++){
// 			if(a[i][j]) tot++;
// 		}
// 	}
// 	return cnt != tot;//是不等于!!!!!
// }

int calc(){
    hascycle = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			vis[i][j] = 0;
			ind[i][j] = 0;
		}
	}
	bool flag = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			if(a[i][j] == 1 && !flag){
                vis[i][j] = 1;
				dfs(i, j, -1, -1);
				flag = 1;
			}
		}
	}

	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			if(a[i][j] == 1 && !vis[i][j]) return 0;
		}
	}
// 	for(int i = 0; i < n; i++){
// 		for(int j = 0; j < m; j++){
// 			if(a[i][j] == 0) continue;
// 			for(int k = 0; k < 4; k++){
// 				int mx = i + dx[k];
// 				int my = j + dy[k];
// 				if(mx < 0 || mx > n - 1 || my < 0 || my > m - 1 || a[mx][my] == 0) continue;
// 				ind[mx][my]++;
// 			}
// 		}
// 	}
	if(hascycle) return 0;	
	int res = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			if(a[i][j] == 1){
				res++;
			}
		}
	}
	return res;
}

void solve(){
	int q;
	
	cin >> n >> m;
	vector<int> vec(n);
	int res = 0;
	bool flag = 0;
	if(n > m){
		swap(n, m);
		flag = 1;
	}
	if(n == 1){
		if(!flag) cout << string(m, '.') << '\n';
		else{
			for(int i = 1; i <= m; i++){
				cout << ".\n";
			}
		}
		return;
	}
    string ans[30];
	if(n * m <= 20){
        for(int x = 0; x < (1LL << (n * m)); x++){
            // for(int x = 0; x <= 3; x++){
            // int x = 3;
            // xx = x;
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    a[i][j] = x >> (i * m + j) & 1;
                }
            }
            hascycle = 0;
            int t = calc();
            // cout << x << ' ' << t << ' ' << hascycle << '\n';
            if(t > res){
                for(int i = 0; i < n; i++){
                    for(int j = 0; j < m; j++){
                        b[i][j] = a[i][j];
                    }
                }
                res = t;
            }
        }
        cout << res << '\n';
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                ans[i][j] = b[i][j] == 1 ? '.' : 'W';
            }
//             cout << '\n';
        }
    }
    else if(n == 2 && m == 11){
        ans[0] = "...........";
        ans[1] = ".W.W.W.W.W.";
    }
    else if(n == 2 && m == 12){
        ans[0] = "............";
        ans[1] = ".W.W.W.W.W.W";
    }
	else if(n == 3 && m == 7){
        ans[0] = ".......";
        ans[1] = ".W.W.W.";
        ans[2] = "..W...W";
    }
    else if(n == 3 && m == 8){
        ans[0] = "........";
        ans[1] = ".WW.W.W.";
        ans[2] = "...W...W";
    }
    else if(n == 4 && m == 6){
        ans[0] = ".......";
        ans[1] = "W.W.W.";
        ans[2] = ".W.W..";
        ans[3] = ".....W";
    }
    else{
        ans[0] = ".....";
        ans[1] = ".W.W.";
        ans[2] = "..W..";
        ans[3] = ".W.W.";
        ans[4] = "....W";
    }
    char ans2[30][30];
    if(!flag){
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                cout << ans[i][j];
            }
            cout << '\n';
        }
        
    }
    else{
        for(int j = 0; j < m; j++){
            for(int i = 0; i < n; i++){
                cout << ans[i][j];
            }
            cout << '\n';
        }
    }
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	int T = 1;
	// cin >> T;
	while(T--){
		solve();
	}
	return 0;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__night_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值