今天又多了两个专题 数论专题一题都没做就又有新得了
直接开一个专题来记录过的题把
以前数据结构那些写的很散
最短路水题 直接过
这题题意都没看懂一开始
看了题解顺便重新学了一下弗洛伊德的写法
不过这题很多毒瘤的地方
最后的输出要多加一个换行符 还有最好用c++
g++无限wa 换c++就a了
这题要求每个路径的最大值中间的最小值
因为数据不大 所以用弗洛伊德暴力跑就行了
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 300+10;
const int inf = 0x1f1f1f1f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
double mp[maxn][maxn];
int n;
struct node
{
int x,y;
}e[maxn];
double cal(int x1,int y1,int x2,int y2)
{
return sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2));
}
int main()
{
int ce=1;
while(~scanf("%d",&n)&&n)
{
ms(mp,0);
for(int i=1;i<=n;i++)
scanf("%d%d",&e[i].x,&e[i].y);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
mp[i][j]=mp[j][i]=sqrt((double)(e[i].x-e[j].x)*(e[i].x-e[j].x)+(double)(e[i].y-e[j].y)*(e[i].y-e[j].y));
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=min(mp[i][j],max(mp[i][k],mp[k][j]));//维护所有路径的最大值中的最小值
printf("Scenario #%d\nFrog Distance = %.3lf\n\n",ce++,mp[1][2]);//这里最后记得多写一个换行符
}
return 0;
}
跟上题思路相似
不过这题是求每条路的最小值中间的最大值
因为数据变大了
所以好像弗洛伊德跑不了了
看了好多题解都是用的dij
但是我看了好久他中间的操作还是不是很明白
看完现在头还是晕的
先放代码上来
等我懂了在写注释把
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1000+10;
const int inf = 0x1f1f1f1f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int n,m;
int dis[maxn];
int mp[maxn][maxn],vis[maxn];
void dij()
{
for(int i=1;i<=n;i++)
{
dis[i]=mp[1][i];
vis[i]=0;
}
for(int i=1;i<=n;i++)
{
int tem=-1;
int x=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]>tem)
{
tem=dis[j];
x=j;
}
}
if(x!=-1)
{
vis[x]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<min(dis[x],mp[x][j]))
dis[j]=min(dis[x],mp[x][j]);
}
}
}
}
int main()
{
int t,ce=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ms(mp,0);
for(int i=1;i<=m;i++)
{
int x,y;
int z;
scanf("%d%d%d",&x,&y,&z);
if(mp[x][y]<z)
{
mp[x][y]=z;
mp[y][x]=z;
}
}
dij();
printf("Scenario #%d:\n",ce++);
printf("%d\n\n",dis[n]);
}
return 0;
}
自闭专题继续更新
题目思路 他要求每个点到x点的距离与x点到每个点的距离之和的最大值
因为题目给边都是单向的 所以就要特殊处理
一开始准备准备每个点跑一边 建一个dij的二维数组记录每次的值
但是一直wa 不知道那里错了
然后看了下题解说正着建一个图 在反着建一个图就好
在两个图上都跑一次dij就好了
题解给的是邻接矩阵的代码
但是我写的一直wa 也找不出哪里错了
就写了个前向星建两个图的 就是有点麻烦 写的时候要细心写不然很容易出bug
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e3+10;
const int inf = 0x1f1f1f1f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int n,m,x,first[maxn],first2[maxn],len1,len2;
int dis1[maxn],dis2[maxn];
int vis[maxn];
struct node
{
int to,next,v;
}e[100000+10],re[100000+10];
void add(int u,int v,int w)
{
e[len1].to=v;
e[len1].next=first[u];
e[len1].v=w;
first[u]=len1++;
re[len2].to=u;
re[len2].next=first2[v];
re[len2].v=w;
first2[v]=len2++;
}
struct point
{
int id;
ll val;
point(int id,ll val)
{
this->id=id;
this->val=val;
}
bool operator<(const point &x)const
{
return val>x.val;
}
};
void dij1(int s)
{
for(int i=0;i<=n+1;i++)
{
dis1[i]=inf;
vis[i]=0;
}
priority_queue<point>q;
q.push(point(s,0));
dis1[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
for(int i=first[rt];~i;i=e[i].next)
{
int id=e[i].to;
if(!vis[id]&&dis1[rt]+e[i].v<dis1[id])
{
dis1[id]=dis1[rt]+e[i].v;
q.push(point(id,dis1[id]));
}
}
}
}
void dij2(int s)
{
for(int i=0;i<=n+1;i++)
{
dis2[i]=inf;
vis[i]=0;
}
priority_queue<point>q;
q.push(point(s,0));
dis2[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
for(int i=first2[rt];~i;i=re[i].next)
{
int id=re[i].to;
if(!vis[id]&&dis2[rt]+re[i].v<dis2[id])
{
dis2[id]=dis2[rt]+re[i].v;
q.push(point(id,dis2[id]));
}
}
}
}
int main()
{
ms(first,-1);
ms(first2,-1);
scanf("%d%d%d",&n,&m,&x);
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dij1(x);
dij2(x);
int maxx=0;
for(int i=1;i<=n;i++)
{
if(dis2[i]!=inf&&dis2[i]!=inf)
maxx=max(maxx,dis1[i]+dis2[i]);
}
printf("%d\n",maxx);
return 0;
}
;
这两题的思路差不多所以放在一起了 算是一种套路的题吧
题目都是要找一个正权回路
因为数据大的时候 弗洛伊德用不了
就都用的是spfa
在跑最短路的时候加一个记录次数的数组
如果某一个结点跑到的次数超过了n次
那么这个节点一定在一个环上
//e题代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 300+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int first[maxn],vis[maxn],f[maxn],len;
double dis[maxn];
struct node
{
int to,next;
double r,c;
}e[maxn<<1];
int n,m,s;
double g;
void add(int u,int v,double r,double c)
{
e[len].to=v;
e[len].r=r;
e[len].c=c;
e[len].next=first[u];
first[u]=len++;
}
bool spfa()
{
for(int i=0;i<=n+1;i++)
{
dis[i]=0;
vis[i]=0;
f[i]=0;
}
dis[s]=g;
vis[s]=1;
f[s]++;
queue<int>q;
q.push(s);
int rt;
while(!q.empty())
{
rt=q.front();
q.pop();
vis[rt]=0;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int v=e[i].to;
double tem=(dis[rt]-e[i].c)*e[i].r;
if(dis[v]<tem)
{
dis[v]=tem;
if(!vis[v])
{
vis[v]=1;
f[v]++;
q.push(v);
if(f[v]>n)
return 1;
}
}
}
}
if(dis[s]>g)return 1;
else return 0;
}
int main()
{
ms(first,-1);
scanf("%d%d%d%lf",&n,&m,&s,&g);
for(int i=1;i<=m;i++)
{
int a,b;
double r1,c1,r2,c2;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2);
add(a,b,r1,c1);
add(b,a,r2,c2);
}
if(spfa())
printf("YES\n");
else
printf("NO\n");
}
//i题代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int n,first[maxn],len,f[maxn],vis[maxn];
double dis[maxn];
string str;
map<string,int>mp;
struct node
{
int to,next;
double z;
}e[maxn];
void add(int x,int y,double z)
{
e[len].to=y;
e[len].z=z;
e[len].next=first[x];
first[x]=len++;
}
bool spfa()
{
for(int i=1;i<=n;i++)
{
dis[i]=0;
vis[i]=0;
f[i]=0;
}
dis[1]=1;
vis[1]=1;
f[1]++;
queue<int>q;
q.push(1);
//print1;
while(!q.empty())
{
int id=q.front();
q.pop();
vis[id]=0;
for(int i=first[id];i!=-1;i=e[i].next)
{
int v=e[i].to;
double tem=dis[id]*e[i].z;
if(tem>dis[v])
{
dis[v]=tem;
if(!vis[v])
{
vis[v]=1;
f[v]++;
q.push(v);
if(f[v]>n)
{
//print1;
return 1;
}
}
}
}
}
if(dis[1]>1)
return 1;
else
return 0;
}
int main()
{
int ce=1;
while(scanf("%d",&n)&&n!=0)
{
ms(first,-1);
mp.clear();
len=0;
int cnt=1;
for(int i=1;i<=n;i++)
{
cin>>str;
mp[str]=cnt++;
}
int q;
scanf("%d",&q);
while(q--)
{
int x,y;
double z;
cin>>str;
x=mp[str];
//printf("ca %d ",x);
cin>>z>>str;
y=mp[str];
//printf("%d\n",y);
add(x,y,z);
}
printf("Case %d: ",ce++);
if((spfa()))printf("Yes\n");
else printf("No\n");
}
}
跟上面两题差不多 都是查环
不过这题要查的是负环
但套路都差不多 就是换一些比较的东西
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e4+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int first[maxn],len,vis[maxn],dis[maxn],f[maxn];
int n,m,w;
struct node
{
int to,next;
int v;
}e[maxn<<1];
void add(int u,int v,int w)
{
e[len].to=v;
e[len].next=first[u];
e[len].v=w;
first[u]=len++;
}
bool spfa(int s)
{
for(int i=0;i<=n+1;i++)
{
dis[i]=inf;
vis[i]=0;
f[i]=0;
}
dis[s]=0;
vis[s]=1;
f[s]++;
queue<int>q;
q.push(s);
while(!q.empty())
{
int rt=q.front();
q.pop();
vis[rt]=0;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(dis[v]>dis[rt]+e[i].v)
{
dis[v]=dis[rt]+e[i].v;
if(!vis[v])
{
vis[v]=1;
f[v]++;
if(f[v]>n)
return 1;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ms(first,-1);
len=0;
scanf("%d%d%d",&n,&m,&w);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
for(int i=1;i<=w;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z*(-1));
}
if(spfa(1))
printf("YES\n");
else
printf("NO\n");
}
}
又是看了题解才晓得咋写的题
题目给出了两个牛之间的关系
可以抽象成一条边
若a赢了b 就记录成mp[a][b]=1 mp[b][a]=-1
因为题目数据小于1e3 所以直接跑弗洛伊德就行
判断的时候如果mp[i][k]==mp[k][j]并且他们都不等于inf
那么i j至今的关系就能确定了 这个关系可以自己理一下
然后在遍历每一个数与其他数之间的关系是否都能确定
如果可以ans++
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e4+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int mp[105][105];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
ms(mp,inf);
for(int i=1;i<=n;i++)
mp[i][i]=0;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=1;
mp[y][x]=-1;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(mp[i][k]==mp[k][j]&&mp[i][k]!=inf)
mp[i][j]=mp[i][k];
}
}
}
int cnt=0;
for(int i=1;i<=n;i++)
{
int flag=0;
for(int j=1;j<=n;j++)
{
if(mp[i][j]==inf)
flag=1;
}
if(flag==0)
cnt++;
}
printf("%d\n",cnt);
}
与d题类似 建两遍图 跑两次最短路
在把所有的值加起来
记得开ll
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
struct node
{
int to,next,v;
}e[maxn<<1],re[maxn<<1];
int len1,len2;
int n,m;
int first[maxn],first2[maxn],vis[maxn];
ll dis1[maxn],dis2[maxn];
void add(int u,int v,int w)
{
e[len1].to=v;
e[len1].next=first[u];
e[len1].v=w;
first[u]=len1++;
re[len2].to=u;
re[len2].next=first2[v];
re[len2].v=w;
first2[v]=len2++;
}
struct point
{
int id;
ll val;
point(int id,ll val)
{
this->id=id;
this->val=val;
}
bool operator <(const point&x)const
{
return val>x.val;
}
};
void dij1(int s)
{
for(int i=0;i<=n+1;i++)
{
vis[i]=0;
dis1[i]=llinf;
}
priority_queue<point>q;
q.push(point(s,0));
dis1[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(!vis[id]&&dis1[rt]+e[i].v<dis1[id])
{
dis1[id]=dis1[rt]+e[i].v;
q.push(point(id,dis1[id]));
}
}
}
}
void dij2(int s)
{
for(int i=0;i<=n+1;i++)
{
vis[i]=0;
dis2[i]=llinf;
}
priority_queue<point>q;
q.push(point(s,0));
dis2[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
for(int i=first2[rt];i!=-1;i=re[i].next)
{
int id=re[i].to;
if(!vis[id]&&dis2[rt]+re[i].v<dis2[id])
{
dis2[id]=dis2[rt]+re[i].v;
q.push(point(id,dis2[id]));
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ms(first,-1);
ms(first2,-1);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
add(x,y,v);
}
dij1(1);
dij2(1);
ll sum=0;
for(int i=2;i<=n;i++)
{
sum+=dis1[i]+dis2[i];
}
printf("%lld\n",sum);
}
}
与上面h题建图方式有些类似
将每条路第一个连着的设为0
其余要该方向才能走的路设为1
跑最短路就好了
因为数据比较小
直接弗洛伊德就行了
记得把mp[i][i]初始化为0
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int n,a,b;
int mp[105][105];
int main()
{
scanf("%d%d%d",&n,&a,&b);
ms(mp,inf);
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
for(int j=1;j<=k;j++)
{
int x;
scanf("%d",&x);
if(j==1)
mp[i][x]=0;
else
mp[i][x]=1;
}
}
for(int i=1;i<=n;i++)
mp[i][i]=0;
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
//printf("%d %d %d %d\n",k,i,j,mp[i][j]);
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
//printf("%d %d %d %d\n",k,i,j,mp[i][j]);
}
}
}
if(mp[a][b]!=inf)
printf("%d\n",mp[a][b]);
else
printf("-1\n");
}
差分约束的题意 抽象之后建图跑最短路就好了
知道怎么建图 这题解释个最短路裸题了
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int first[maxn],vis[maxn];
int dis[maxn],len;
int n,m;
struct node
{
int to,next;
int v;
}e[maxn<<1];
void add(int u,int v,int w)
{
e[len].to=v;
e[len].v=w;
e[len].next=first[u];
first[u]=len++;
}
struct point
{
int id;
ll val;
point(int id,ll val)
{
this->id=id;
this->val=val;
}
bool operator<(const point &x)const
{
return val>x.val;
}
};
void dij(int s)
{
for(int i=0;i<=n+1;i++)
{
dis[i]=inf;
vis[i]=0;
}
priority_queue<point>q;
q.push(point(s,0));
dis[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(!vis[id]&&dis[rt]+e[i].v<dis[id])
{
dis[id]=dis[rt]+e[i].v;
q.push(point(id,dis[id]));
}
}
}
}
int main()
{
ms(first,-1);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
add(x,y,v);
}
dij(1);
int maxx=0;
for(int i=1;i<=n;i++)
{
if(dis[i]!=inf)
maxx=max(dis[i],maxx);
}
printf("%d\n",maxx);
}
题目用类似矩阵的方式给出边权值 直接建图跑最短路 求最大路径就好
唯一的难点就是输入会有x
所以应该是输入字符型而不是整型
开始觉得字符型再转整型挺麻烦的
看了题解说直接用atoi这个函数来把字符串数组转变成整型
又学到了新东西
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
ll dis[maxn];
int vis[maxn],first[maxn],len;
int n;
struct node
{
int to,next,v;
}e[maxn<<1];
void add(int u,int v,int w)
{
e[len].to=v;
e[len].v=w;
e[len].next=first[u];
first[u]=len++;
}
struct point
{
int id;
ll val;
point(int id,ll val)
{
this->id=id;
this->val=val;
}
bool operator<(const point &x)const
{
return val>x.val;
}
};
void dij(int s)
{
for(int i=0;i<=n+1;i++)
{
dis[i]=llinf;
vis[i]=0;
}
priority_queue<point>q;
q.push(point(s,0));
dis[s]=0;
//print1;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(!vis[id]&&dis[rt]+e[i].v<dis[id])
{
dis[id]=dis[rt]+e[i].v;
q.push(point(id,dis[id]));
}
}
}
}
int main()
{
ms(first,-1);
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
{
char x[20];
scanf("%s",x);
if(x[0]!='x')
{
int w=atoi(x);
add(i,j,w);
add(j,i,w);
}
}
}
dij(1);
ll maxx=0;
for(int i=1;i<=n;i++)
if(dis[i]!=llinf)
maxx=max(maxx,dis[i]);
printf("%lld\n",maxx);
}
昨天的自闭多校 摸了一下午鱼 过了几道简单题之后
困得不行 写题目也写不进
晚上整个就处于一种快要死掉的状态
看了下题目 一脸懵逼得过了s题
说实话对差分约束还是挺懵逼得
其实挺容易看出来是差分约束的
有两种情况
x-y>=z
a-b<=c
第一种情况就是我们跑最短路建图是需要的样子
第二种情况我们其实也能变成第一种
直接成一个-1
式子就变成了
b-a>=-c 这样就能一起建图了
但是这样也让图里面可能又负环
所以要送spfa跑最短路得同时 判断是否有负环有的话就退出
最后的输出要注意 之前就没搞清楚
负环是使得无法跑到终点 所以没有答案 应该输出-1
最后的值等于inf则是说两点不连通 所以他们的距离可以为任意距离
所以输出-2
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
struct node
{
int to,next;
ll v;
}e[maxn];
int first[maxn],vis[maxn],f[maxn],len;
ll dis[maxn];
int n,ml,mr;
void add(int u,int v,int w)
{
e[len].to=v;
e[len].next=first[u];
e[len].v=w;
first[u]=len++;
}
void spfa(int st)
{
for(int i=0;i<=n+1;i++)
{
dis[i]=llinf;
vis[i]=0;
f[i]=0;
}
dis[st]=0;
vis[st]=1;
f[st]++;
int flag=0;
queue<int>q;
q.push(st);
while(!q.empty())
{
st=q.front();
q.pop();
vis[st]=0;
for(int i=first[st];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(dis[id]>dis[st]+e[i].v)
{
dis[id]=dis[st]+e[i].v;
if(!vis[id])
{
f[id]++;
vis[id]=1;
if(f[id]>n)
{
flag=2;
break;
}
q.push(id);
}
}
}
}
if(flag==2)
printf("-1\n");
else if(dis[n]==llinf)
printf("-2\n");
else
printf("%lld\n",dis[n]);
}
int main()
{
scanf("%d%d%d",&n,&ml,&mr);
len=0;
ms(first,-1);
for(int i=1;i<=ml;i++)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
}
for(int i=1;i<=mr;i++)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
add(y,x,(-1)*z);
}
spfa(1);
}
题目给出了一个层的概念
可以根据层建一个 相邻层到点距离为c 自己在的层的点和自己的距离为0
这样建图跑最短路 还要就是自己在的层到自己的边只建一个单向边
其他的记得见双向的
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 5e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 2333;
int n,m;
ll c;
int len;
int first[maxn],vis[maxn];
ll dis[maxn];
struct node
{
int to,next,v;
}e[maxn<<1];
void add(int u,int v,int w)
{
e[len].to=v;
e[len].v=w;
e[len].next=first[u];
first[u]=len++;
}
struct point
{
int id;
ll val;
point(int id,ll val)
{
this->id=id;
this->val=val;
}
bool operator<(const point &x)const
{
return val>x.val;
}
};
void dij(int s)
{
for(int i=1;i<=maxn;i++)
dis[i]=llinf;
ms(vis,0);
priority_queue<point>q;
q.push(point(s,0));
dis[s]=0;
while(!q.empty())
{
int rt=q.top().id;
q.pop();
if(vis[rt])continue;
vis[rt]=1;
if(rt==n)return;
for(int i=first[rt];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(!vis[id]&&dis[rt]+e[i].v<dis[id])
{
dis[id]=dis[rt]+e[i].v;
q.push(point(id,dis[id]));
}
}
}
}
int main()
{
int t,ce=1;
scanf("%d",&t);
while(t--)
{
ms(first,-1);
scanf("%d%d%lld",&n,&m,&c);
len=0;
for(int i=1;i<=n;i++)
{
int l;
scanf("%d",&l);
//add(i,l+n,0);
add(l+n,i,0);
if(l-1>0)
{
add(i,l+n-1,c);
add(l+n-1,i,c);
}
add(i,l+n+1,c);
add(l+n+1,i,c);
}
for(int i=1;i<=m;i++)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dij(1);
printf("Case #%d: ",ce++);
if(dis[n]==llinf)
printf("-1\n");
else
printf("%lld\n",dis[n]);
}
}
更完这一题最短路专题就差不多结束了 其实还有几题没写
但是新的字典树的专题又来了 图论的也没写多少
要把这些也补补 准备一下选拔赛了 虽然应该是垫底
但是希望不要差太多