P2243 电路维修

P2243 电路维修

首先我们需要将每个格点提取出来。

然后将给定图的补图建出来,并且与原图合并。合并时原图的边权都为0,补图的边权都为1。

如此建图(图论就是考建图,算法就那么几个),如果不旋转,则通过这条边的费用为0,旋转的话就是1.右上角到左下角的最短路就是旋转次数。

#include<algorithm>
#include<iostream>
#include<cstring>
using std::swap;
const int maxn=253000;
struct Link
{
	int point;
	int weight;
	int nxt;
};
Link line[maxn<<2];
char data[1000];
int dis[maxn];
bool vis[maxn];
int head[maxn],tail;
void add(int a,int b,int c)
{
	line[++tail].point=b;
	line[tail].weight=c;
	line[tail].nxt=head[a];
	head[a]=tail;
}
struct node
{
	int p;
	int v;
	bool operator < (const node &a)	const
	{
		return v<a.v;
	}
};
node base[20000000];
int len;
node top()
{
	return base[1];
}
void push(node a)
{
	base[++len]=a;
	int pos=len;
	while((pos>>1)&&base[pos]<base[pos>>1])
	{
		swap(base[pos],base[pos>>1]);
		pos>>=1;
	}
	return ;
}
void pop()
{
	swap(base[1],base[len--]);
	int pos=1,nxt;
	while(true)
	{
		nxt=pos;
		if(base[pos<<1]<base[nxt]&&(pos<<1)<=len)
			nxt=pos<<1;
		if(base[pos<<1|1]<base[nxt]&&(pos<<1|1)<=len)
			nxt=pos<<1|1;
		if(pos==nxt)	break;
		swap(base[pos],base[nxt]);
		pos=nxt;
	}
	return ;
}
int main()
{	int ha;
	scanf("%d",&ha);
	while(ha--)
	{
		memset(head,0,sizeof(head));
		tail=0;
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			scanf("%s",data+1);
			for(int j=1;j<=m;j++)
			{
				int a=1,b=0;
				if(data[j]=='/')
					swap(a,b);
				add((m+1)*(i-1)+j,(m+1)*i+j+1,b);
				add((m+1)*i+j+1,(m+1)*(i-1)+j,b);
				add((m+1)*(i-1)+j+1,(m+1)*i+j,a);
				add((m+1)*i+j,(m+1)*(i-1)+j+1,a);
			}
		}
		memset(dis,100,sizeof(dis));
		memset(vis,false,sizeof(vis));
		dis[1]=0;
		node pas;pas.p=1;pas.v=0;
		push(pas);
		int get=0;
		while(len)
		{
			pas=top();
			while(vis[pas.p]&&len)
			{
				pop();
				pas=top();
			}
			if(!len)	break;
			get++;
			vis[pas.p]=true;
			dis[pas.p]=pas.v;
			for(int i=head[pas.p];i;i=line[i].nxt)
				if(dis[line[i].point]>dis[pas.p]+line[i].weight&&!vis[line[i].point])
				{
					dis[line[i].point]=dis[pas.p]+line[i].weight;
					node nxt;
					nxt.p=line[i].point;
					nxt.v=dis[line[i].point];
					push(nxt);
				}
		}
		if(dis[(m+1)*(n+1)]==1684300900)
			printf("NO SOLUTION\n");
		else
			printf("%d\n",dis[(m+1)*(n+1)]);		
	}

}
posted @ 2018-07-26 16:57  Lance1ot  阅读(367)  评论(0编辑  收藏  举报