电路维修

【题目描述】:
电路维修

【思路】:
开先看起来挺迷的,觉得没法做,搜索也写不出来。。。

再仔细分析题目,发现对于任意一根电路,它只有两种状态:

  • 连着右上和坐下
  • 连着左下和右上

要求最小的操作数。
我们可以发现,每条电线可以花费1的代价从一种状态改变为另外一种状态,那么我们可以对于已经连着的两点连一条权为0的边,没连着的连一条花费为1的边,求出从左上角到右下角的最短路即可。
注:卡\(SPFA\),建议用\(SLF\) \(or\) \(LLL\) \(or\) 堆优化的\(DJ\),此处用的\(SLF\)优化。

#include<cstdio>
#include<queue>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;

int n,m;

const int MAXN = 251005;

struct edge{
    int u,v,w,nxt;
}e[MAXN<<2];int head[MAXN];int cnt = 0;int ed;int dis[MAXN];bool vis[MAXN];char c[505];

inline void add(int u,int v,int w){
    e[++cnt].u = u;e[cnt].v = v;e[cnt].w = w;e[cnt].nxt = head[u];head[u] = cnt;
}

deque<int>q;
inline void spfa(){
    q.push_back(1);
    memset(vis,0,sizeof vis);
    memset(dis,inf,sizeof dis);
    dis[1] = 0;
    
    while(!q.empty()){
        int u = q.front();q.pop_front();vis[u] = 0;
        for(int i=head[u];i;i=e[i].nxt){
            int v = e[i].v;
            if(dis[v] > dis[u] + e[i].w){
                dis[v] = dis[u] +e[i].w;
                if(!vis[v]){
                    vis[v] = 1;
                    if(e[i].w == 0) q.push_front(v);
                    else q.push_back(v);
                }
            }
        }
    }
    
    printf("%d\n",dis[ed]);
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        memset(head,0,sizeof head);cnt = 0;
        for(int i=1;i<=n;++i){
            scanf("%s",c+1);
            for(int j=1;j<=m;++j){
                if(c[j] == '/'){
                    add(j+1+(i-1)*(m+1) , j+i*(m+1) , 0);
                    add(j+i*(m+1) , j+1+(i-1)*(m+1) , 0);
                    add(j+(i-1)*(m+1) , j+1+i*(m+1) , 1);
                    add(j+1+i*(m+1) , j+(i-1)*(m+1) , 1);
                    
                }
                else{
                    add(j+1+(i-1)*(m+1) , j+i*(m+1) , 1);
                    add(j+i*(m+1) , j+1+(i-1)*(m+1) , 1);
                    add(j+(i-1)*(m+1) , j+1+i*(m+1) , 0);
                    add(j+1+i*(m+1) , j+(i-1)*(m+1) , 0);
                }
            }
        }
        if((n+m)%2) {puts("NO SOLUTION");continue;}
        ed = (n + 1) * (m + 1);
        spfa();
    }
    return 0;
}
posted @ 2018-10-04 22:46  lajioj  阅读(237)  评论(0编辑  收藏  举报