试题编号: | 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个,其中的任意两个城市都是便利城市对,数量为,亦即
,将每个强连通分量的便利城市对个数累加,即是答案。
#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;
}