整理04

试题编号:201403-4
试题名称:无线网络(选第二个编译器,否则出错)

SPFA模板

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define NMAX 210
#define INF 0x3f3f3f3f

struct node{
	int x,y;
	node(){
	}
	node(int a,int b):x(a),y(b){
	}
}p[NMAX];
int n,m,k,r;
node cur,next;
int d[NMAX][NMAX];
//d[i][j]表示从源点到i节点,其中增加j个路由器的路径的最短路径
int vis[NMAX][NMAX];
//vis[i][j]表示从源点到i节点,其中增加j个路由器的路径信息是否在栈中
int G[NMAX][NMAX];//邻接矩阵 
void spfa(node start){
	//x当前节点,y增加路由器个数
	queue<node> q;
	memset(d,INF,sizeof(d)); 
	memset(vis,0,sizeof(vis));
	d[0][0]=0;
	vis[0][0]=1;
	q.push(start);
	while(!q.empty()){
		cur=q.front();
		q.pop();
		vis[cur.x ][cur.y ]=0;//弹出栈 
		for(int i=0;i<n+m;i++){
			if(G[cur.x][i]){
				next.x =i;
				next.y =cur.y ;
				if(i>=n){
					++next.y ;
				}
				if(next.y<=k&&d[next.x ][next.y ]>d[cur.x ][cur.y ]+1){
					d[next.x ][next.y ]=d[cur.x ][cur.y ]+1;
					if(!vis[next.x ][next.y ]){//满足条件,记录入栈 
						vis[next.x ][next.y ]=1;
						q.push(next);
					}
				//	cout<<d[next.x ][next.y ]<<endl;
				} 
				
			}
		}
	}
} 
int main(){
	cin>>n>>m>>k>>r;
	for(int i=0;i<n+m;i++){
		cin>>p[i].x >>p[i].y ;
	} 
	for(int i=0;i<n+m;i++){
		for(int j=i+1;j<n+m;j++){
			ll dis=(ll)(p[i].x -p[j].x )*(ll)(p[i].x -p[j].x )+(ll)(p[i].y -p[j].y )*(ll)(p[i].y -p[j].y );
			if(dis<=(ll)r*r){
				G[i][j]=G[j][i]=1;
			}
		}
	}
	spfa(node(0,0));
	int cost=INF;
	for(int i=0;i<=k;i++){
		cost=min(d[1][i],cost);
	}
	cout<<cost-1<<endl;
	return 0;
}
试题编号:201409-4
试题名称:最优配餐

 注意long long    BFS

#include<cstdio>
#include<queue>
using namespace std;
const int MAX_SIZE = 1000;
struct point_info{
	int x,y;
	long long step;
};
bool Legal(int x,int y,int n){
	if(x<1||x>n||y<1||y>n)
		return false;
	return true;
}
long long customer_need[MAX_SIZE+1][MAX_SIZE+1] = {0LL};//记录一个点所有顾客的总需求 
int customers[MAX_SIZE+1][MAX_SIZE+1] = {0};//记录同一点有几个顾客 
 
int main(){
	int n,m,k,d,x,y;
	long long ans = 0,value;
	queue<point_info> q;
	bool ban[MAX_SIZE+1][MAX_SIZE+1] = {false};
	point_info front,t;
	const int move[][2] = {{0,1},{1,0},{0,-1},{-1,0}};
	scanf("%d %d %d %d",&n,&m,&k,&d);
	while(m--){
		point_info start;
		start.step = 0LL;
		scanf("%d %d",&start.x,&start.y);
		ban[start.x][start.y] = true;
		q.push(start);
	}
	for(int i=0;i<k;i++){
		scanf("%d %d %lld",&x,&y,&value);
		customer_need[x][y] += value;
		customers[x][y]++; //在一个位置可能有多个人 
	}
	while(d--){
		scanf("%d %d",&x,&y);
		ban[x][y] = true;
	}
	while(!q.empty()){
		front = q.front();
		q.pop();
		
		if(customer_need[front.x][front.y]!=0LL){
			k -= customers[front.x][front.y];
			ans += front.step * customer_need[front.x][front.y];
		//	printf("f.x=%d,f.y=%d\n",front.x ,front.y );
			if(k==0)//谁先找到谁就是最短的,直接跳出即可 
				break;
		}
		for(int i=0;i<4;i++){
			x = front.x+move[i][0];
			y = front.y+move[i][1];
			if(Legal(x,y,n)&&!ban[x][y]){
				t.x = x;
				t.y = y;
				t.step = front.step + 1;
				ban[x][y] = true;
				q.push(t);	
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}
试题编号:201412-4
试题名称:最优灌溉(prim)
#include<bits/stdc++.h>
using namespace std;
#define inf 0x7f7f7f7f 
int n,m;
int a,b,c,dis[1001],p[1001][1001];
int sum=0,flag;
int prim(){
	 for(int i=2;i<=n;i++){
	 	dis[i]=p[1][i];
	 }
	 for(int i=0;i<n-1;i++){
	 	int temp=inf;
	 	for(int j=2;j<=n;j++){//找到最短的 
	 		if(dis[j]!=-1&&dis[j]<temp){
	 			temp=dis[j];
	 			flag=j;
			 }
		 }
		 sum+=temp;
		 dis[flag]=-1;
		 for(int k=2;k<=n;k++){//更新dis表 
		 	if(dis[k]!=-1&&dis[k]>p[flag][k]){
		 		dis[k]=p[flag][k];
			 }
		 }
	 }
	 return sum;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			p[i][j]=inf;
		}
	}
	for(int i=0;i<m;i++){
		cin>>a>>b>>c;
		p[a][b]=c;
		p[b][a]=c;
	}
	cout<<prim()<<endl;
	
	return 0;
} 
试题编号:201503-4
试题名称:网络延时

样例输入

4 2
1 1 3
2 1

样例输出

4

样例说明

  样例的网络连接模式如下,其中圆圈表示交换机,方框表示电脑:

 


  其中电脑1与交换机4之间的消息传递花费的时间最长,为4个单位时间。

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define inf 0x7f7f7f7f 
int n,m,u;
bool vis[20001];
int dis[200001];
vector<int>v[200001];
int main(){
	memset(dis,0,sizeof(dis));
	cin>>n>>m;
	for(int i=2;i<=n+m;i++){
		cin>>u;
		v[i].push_back(u);
		v[u].push_back(i);//建立邻接表 
	}
	vis[1]=true;
	queue<int>q;
	q.push(1);
	int now;
	while(!q.empty() ){//第一次bfs,找最远点 
		 now=q.front() ;
		q.pop() ;
		for(int i=0;i<v[now].size() ;i++){
			int t=v[now][i];
			if(vis[t]) continue;
			vis[t]=true;
			q.push(t); 
		}
	}
	memset(vis,false,sizeof(vis));
	vis[now]=true;
	q.push(now);
	 	while(!q.empty() ){//第二次bfs,在最远点基础上找他的找最远点 
		 now=q.front() ;
		q.pop() ;
		for(int i=0;i<v[now].size() ;i++){
			int t=v[now][i];
			if(vis[t]) continue;
			vis[t]=true;
			dis[t]=dis[now]+1; 
			q.push(t); 
		}
	}
	 cout<<dis[now]<<endl;
	
	return 0;
} 
试题编号:201509-4
试题名称:高速公路

Tarjan强连通分量算法的模板题

求得强连通分量后,包含的点为cnt个,其中的任意两个城市都是便利城市对,数量为n = C\binom{cnt}{2},亦即n = cnt*(cnt-1)/2,将每个强连通分量的便利城市对个数累加,即是答案。

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e4+10;
int n,m;
int dfn[maxn],low[maxn],vis[maxn],index,ans=0;
vector<int> G[maxn];
stack<int> S;
void tarjan(int u){
	dfn[u]=low[u]=++index;
	S.push(u);
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!vis[v]){
			low[u]=min(dfn[v],low[u]);
		}
	}
	if(low[u]==dfn[u]){
		int cnt=0;
		while(1){
			int x=S.top();
			S.pop();
			cnt++;
			vis[x]=1;
			if(x==u){
				ans+=(cnt-1)*cnt/2;
				break;
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v;
		G[u].push_back(v);
	}
	index=0;
	memset(vis,0,sizeof(vis));
	memset(dfn,0,sizeof(dfn));
	for(int i=1;i<=n;i++){
		if(!dfn[i])
		tarjan(i);
	}
	cout<<ans<<endl;
return 0;
}
试题编号:201512-4
试题名称:送货

注意题目要求从1号节点出发。

欧拉路存在的条件:

无向图:

存在欧拉回路的条件:原图连通,每个节点均为偶度节点。

存在欧拉通路的条件:存在欧拉回路,或原图连通,有两个节点为奇度节点,其他节点均为偶度节点。

有向图:

存在欧拉回路的条件:基图(有向边变成无向边)连通,每个节点的入度等于出度。

存在欧拉通路的条件:存在欧拉回路,或基图连通,有一个节点入度等于出度+1,有一个节点出度等于入度+1,其他节点入度等于出度。

(70分)没处理等于 -1的情况,纯模板https://www.cnblogs.com/acxblog/p/7390301.html

#include<bits/stdc++.h>
#include<set>
using namespace std;
const int N=1e5+7;
multiset<int> to[N];
int len[N];
int road[N],k;
multiset<int>::iterator a;
void dfs(int x){
    for( a=to[x].begin();a!=to[x].end();a=to[x].begin()){
        int u=*a;
        to[x].erase(a);
        to[u].erase(to[u].find(x));//删边 
        dfs(u);//递归 
    }
    
    road[k++]=x;//往答案队列里插入答案 
}

int main(){
    int n,m,a,b;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        len[a]++,len[b]++;
        to[a].insert(b);
        to[b].insert(a);
    }
    int s=-1,e=-1;//起点与终点 
    for(int i=1;i<=n;i++)
        if(len[i]%2==1){
            if(s==-1)s=i;
            else if(e==-1)e=i;
            //else exit(1);
        }//判断每个点的度数 
    if(s==-1)s=1;
    dfs(s);//开始递归 
    	for(k=k-1;k>=0;k--)
        printf("%d ",road[k]);//倒序输出答案 
	
    
    return 0;
}

(100分)

#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
typedef pair<int,int> P;
const int MAX_N=1e5+7;
int n,m,father[MAX_N];
vector<int> G[MAX_N],vs;
int findFather(int x)
{
    return father[x]==x?x:father[x]=findFather(father[x]);
}
void dfs(int u)
{
    int v;
    stack<int> st;
    st.push(u);
    while(!st.empty())
    {
        u=st.top();
        if(G[u].size())//继续向下搜索
        {
            v=G[u].back(); G[u].pop_back();
            vector<int>::iterator it=find(G[v].begin(),G[v].end(),u);//删除边
            G[v].erase(it,it+1);
            st.push(v);
        }
        else//叶子节点,回溯
        {
            vs.push_back(u);
            st.pop();
        }
    }
}
bool solve()
{
    int u=-1,cnt=0;
    for(int i=1;i<=n;i++)//验证连通性
        if(findFather(1)!=findFather(i)) return false;
    for(int i=1;i<=n;i++)
    {
        if(!G[i].size()) continue;
        if(G[i].size()%2)//度数为奇数
        {
            cnt++;
            if(u==-1) u=i;
        }
        if(cnt>2) return false;
        sort(G[i].rbegin(),G[i].rend());
    }
    if(u==-1) u=1;//仅1个顶点
    dfs(u);
    return true;
}
int main()
{
    int u,v;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i=1;i<=n;i++) father[i]=i;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<G[i].size();j++)
            father[findFather(i)]=findFather(G[i][j]);
    }
    if(solve()) for(int i=vs.size()-1;i>=0;i--) cout<<vs[i]<<' ';
    else cout<<-1;
    return 0;
}


试题编号:201604-4
试题名称:游戏
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+7;
int dir_r[4]={0,-1,0,1},dir_c[4]={-1,0,1,0};
struct node{
	int r,c,t;
	node(){}
	node(int r, int c,int t):r(r),c(c),t(t){
	}
};
int vis[maxn][maxn][maxn*2];
int n,m;
int bfs(){
	int tt,rr,cc;
	node u;
	queue<node> que;
	que.push(node(1,1,0));
	while(!que.empty()){
		u=que.front();
		que.pop();
		if(u.r ==n&&u.c ==m) return u.t ;
		for(int i=0;i<4;i++){
			rr=u.r +dir_r[i];
			cc=u.c +dir_c[i];
			tt=u.t +1;
			if(rr<1||rr>n||cc<1||cc>m||vis[rr][cc][tt]){
				continue;
			}
			que.push(node(rr,cc,tt));
			vis[rr][cc][tt]=1;
		}
	}
}
int main(){
	int t,r,c,a,b;
	cin>>n>>m>>t;
	while(t--){
		cin>>r>>c>>a>>b;
		for(int i=a;i<=b;i++)
		vis[r][c][i]=1;
	}
	cout<<bfs();
	return 0;
	
} 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值