电路维修
题目:
提交链接:https://www.luogu.com.cn/problem/T282123
题目背景
达达是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女翰翰,从而被收留在地球上。
题目描述
翰翰的家里有一辆飞行车。 有一天飞行车的电路板突然出现了故障,导致无法启动。 电路板的整体结构是一个 R 行 C 列的网格(R,C≤500),如下图所示。
每个格点都是电线的接点,每个格子都包含一个电子元件。 电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。 在旋转之后,它就可以连接另一条对角线的两个接点。 电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。 达达发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。 她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。 不过,电路的规模实在是太大了,达达并不擅长编程,希望你能够帮她解决这个 问题。
输入格式
输入文件包含多组测试数据。 第一行包含一个整数 T,表示测试数据的数目。 对于每组测试数据,第一行包含正整数 R 和 C,表示电路板的行数和列数。 之后 R 行,每行 C 个字符,字符是" / “和” \ "中的一个,表示标准件的方向。
输出格式
对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。 如果无论怎样都不能使得电源和发动机之间连通,输出 NO SOLUTION
输入输出样例
输入 #1
1
3 5
\\/\\
\\///
/\\\\
输出 #1
1
说明/提示
1≤R,C≤500 , 1≤T≤5
解析:
这里是算能到最后元件的旋转的次数,即从(1,1)到(r+1,c+1)联通所需要的旋转次数
最先能想到的是搜索~~(但是我没有写~~
然后我们再来看,如果两个点最先开始是联通的那通过的时候的代价就是0,如果不连通通过的代价就是1(因为再转一次就会恢复,就是不优的)。
这样一看像不像两点之间的用边权为0或1连接起来的图。
那从起点到终点的最小代价就是在起点到终点求的最短路。当然因为边权只有0和1你可以写一个双边队列。
注意写最短路时最好用Dijkstra,这道题是稠密图用spfa会被卡。这里有多组数据,所以要注意初始化
还有就是要从0开始建边,为什么不从1开始?(因为我写挂了
浅附一个spfa(只有70分)
//电路维修
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 2500005;
const int inf = 0x3f3f3f3f;
struct Edge
{
int u,v,w,nex;
}E[MAXN<<1];
int n,t,r,c,dis[MAXN];
char di;
bool vis[MAXN];
int head[MAXN],tot;
inline void in()
{
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
memset(head,0,sizeof(head));
}
inline void Add_Edge(int u,int v,int w)
{
E[tot].u=u,
E[tot].v=v,
E[tot].w=w,
E[tot].nex=head[u],
head[u]=tot++;
}
inline int read()
{
int k=0,f=1;
char c=getchar();
while(!isdigit(c))
{
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c))
{
k=k*10+(c-48);
c=getchar();
}
return f*k;
}
inline void spfa(int u)
{
int i,v,w;
vis[u]=true,dis[u]=0;
queue<int>q;
q.push(u);
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=false;
for(i=head[u];i;i=E[i].nex)
{
v=E[i].v,w=E[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
q.push(v);
vis[v]=true;
}
}
}
}
}
int main()
{
t=read();
int i,j,ans;
while(t--)
{
r=read(),c=read(),ans=0,tot=0,++c;
in();
for(i=0;i<r;++i)
for(j=0;j<c-1;++j)
{
// scanf("%c",&di[i][j]);
cin >> di;
if(di=='/')
{
Add_Edge(i*c+j+1,(i+1)*c+j,0);
Add_Edge((i+1)*c+j,i*c+j+1,0);
Add_Edge(i*c+j,(i+1)*c+j+1,1);
Add_Edge((i+1)*c+j+1,i*c+j,1);
}
else
{
Add_Edge(i*c+j+1,(i+1)*c+j,1);
Add_Edge((i+1)*c+j,i*c+j+1,1);
Add_Edge(i*c+j,(i+1)*c+j+1,0);
Add_Edge((i+1)*c+j+1,i*c+j,0);
}
}
if((r+c-1)&1)
{
printf("NO SOLUTION\n");
continue;
}
spfa(0),++r;
printf("%d\n",dis[r*c-1]);
}
return 0;
}
AC代码
//电路维修
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 2500005;
const int inf = 0x3f3f3f3f;
struct Edge
{
int u,v,w,nex;
}E[MAXN<<1];
int n,t,r,c,dis[MAXN],pre[MAXN];
char di;
bool vis[MAXN];
int head[MAXN],tot;
inline void in()
{
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
memset(head,0,sizeof(head));
}
inline void Add_Edge(int u,int v,int w)
{
E[tot].u=u,
E[tot].v=v,
E[tot].w=w,
E[tot].nex=head[u],
head[u]=tot++;
}
inline int read()
{
int k=0,f=1;
char c=getchar();
while(!isdigit(c))
{
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c))
{
k=k*10+(c-48);
c=getchar();
}
return f*k;
}
struct Node
{
int num;
int val;
};
priority_queue<Node>q;
bool operator<(Node a,Node b)
{
return a.val>b.val;
}
int main()
{
// freopen("cir.in","r",stdin);
// freopen("cir.out","w",stdout);
t=read();
int i,j,ans,u,v,w;
while(t--)
{
r=read(),c=read(),ans=0,tot=0,++c;
in();
for(i=0;i<r;++i)
for(j=0;j<c-1;++j)
{
// scanf("%c",&di[i][j]);
cin >> di;
if(di=='/')
{
Add_Edge(i*c+j+1,(i+1)*c+j,0);
Add_Edge((i+1)*c+j,i*c+j+1,0);
Add_Edge(i*c+j,(i+1)*c+j+1,1);
Add_Edge((i+1)*c+j+1,i*c+j,1);
}
else
{
Add_Edge(i*c+j+1,(i+1)*c+j,1);
Add_Edge((i+1)*c+j,i*c+j+1,1);
Add_Edge(i*c+j,(i+1)*c+j+1,0);
Add_Edge((i+1)*c+j+1,i*c+j,0);
}
}
if((r+c-1)&1)
{
printf("NO SOLUTION\n");
continue;
}
++r;
dis[0]=0;
Node s;
s.num=0,s.val=0,q.push(s);
for(i=0;i<=r*c&&!q.empty();++i)
{
do
{
s=q.top();
q.pop();
}while(vis[s.num]&&!q.empty());
u=s.num,vis[u]=1;
for(j=head[u];j;j=E[j].nex)
{
v=E[j].v,w=E[j].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
Node sv;
sv.num=v,sv.val=dis[v];
q.push(sv);
}
}
}
printf("%d\n",dis[r*c-1]);
}
return 0;
}
完结撒花✿✿ヽ(°▽°)ノ✿