Paint the Grid Reloaded ZOJ - 3781(缩点 最短路)

ZOJ - 3781

 

把每个连通块缩点,相邻的点建边

然后从某点出发,求到所有点的最短路 取其中最大的值

然后遍历所有的点为起点

取最小值

 

遍历起点 就相当于 第一次操作 翻动该点(是一个连通块) 然后该点就和与它相邻的所有的点的颜色都一样了 然后翻动下一个点····

直到路径最长的点 那么所有的点的颜色就都一样了

每次翻动一个连通块,就相当于把这个连通块和其相邻但不同色的连通块变成了一样的颜色,这样就相当于在新建的图上‘走了’一步,

 

为什么能想到???

咱也不敢问 咱也不敢说 

这也许就是图论的神奇之处吧

 

 

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <list>
#include <cmath>
#include <bitset>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define rb(a) scanf("%lf", &a)
#define rf(a) scanf("%f", &a)
#define pd(a) printf("%d\n", a)
#define plld(a) printf("%lld\n", a)
#define pc(a) printf("%c\n", a)
#define ps(a) printf("%s\n", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 11000, INF = 0x7fffffff;
int n, m;
string str[50];
int dis[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

int vis[50][50], vis3[maxn];
int d[maxn];
int head[maxn], nex[maxn << 1], cnt;
int ans;
set<int> vis2[5000];

struct node
{
    int u, v, w;
}Node[maxn << 1];

void add_(int u, int v, int w)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].w = w;
    nex[cnt] = head[u];
    head[u] = cnt++;
}

void add(int u, int v, int w)
{
    add_(u, v, w);
    add_(v, u, w);
}


void dfs(int x, int y)
{

    for(int i = 0; i < 4; i++)
    {
        int nx = x + dis[i][0];
        int ny = y + dis[i][1];
        if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
        if(str[nx][ny] == str[x][y] && !vis[nx][ny])
        {
            vis[nx][ny] = ans;
            dfs(nx, ny);
        }
        else if(str[nx][ny] != str[x][y] && vis[nx][ny] && !vis2[ans].count(vis[nx][ny]))
        {
            add(vis[nx][ny], ans, 1);
            vis2[vis[nx][ny]].insert(ans);
            vis2[ans].insert(vis[nx][ny]);
        }
    }
}

int spfa(int s)
{
    for(int i = 0; i < maxn; i++) d[i] = INF;
    mem(vis3, 0);
    deque<int> Q;
    Q.push_back(s);
    vis3[s] = 1;
    d[s] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop_front();
        vis3[u] = 0;
        for(int i = head[u]; i != -1; i = nex[i])
        {
            int v = Node[i].v;
            if(d[v] > d[u] + Node[i].w)
            {
                d[v] = d[u] + Node[i].w;
                if(!vis3[v])
                {
                    if(Q.empty()) Q.push_back(v);
                    else if(d[Q.front()] > d[v]) Q.push_front(v);
                    else Q.push_back(v);
                    vis3[v] = 1;
                }
            }
        }
    }
    int mx = -INF;
    for(int i = 1; i <= ans; i++)
        mx = max(mx, d[i]), cout << s << "  " << i << "  " << d[i] << endl;
    return mx;
}

void init()
{
    cnt = ans = 0;
    mem(head, -1);
    mem(vis, 0);
    for(int i = 0; i < 5000; i++) vis2[i].clear();
}


int main()
{
    int T;
    rd(T);
    while(T--)
    {
        init();
        rd(n), rd(m);
        for(int i = 0; i < n; i++)
        {
            cin >> str[i];
        }
        for(int i = 0; i < n; i++)
        {
            for(int j = 0;j < m; j++)
            {
                if(!vis[i][j]) vis[i][j] = ++ans, dfs(i, j);
            }
        }
        cout << ans << endl;
        int ret = INF;
        for(int i = 1; i <= ans; i++)
        {
            ret = min(ret, spfa(i));

        }
        pd(ret);
    }
    return 0;
}

 

posted @ 2019-05-01 21:08  WTSRUVF  阅读(150)  评论(0编辑  收藏  举报