题目描述
给定一个 nn 个点的有向图,请求出图中是否存在从顶点 11 出发能到达的负环。
负环的定义是:一条边权之和为负数的回路。
输入格式
本题单测试点有多组测试数据。
输入的第一行是一个整数 TT,表示测试数据的组数。对于每组数据的格式如下:
第一行有两个整数,分别表示图的点数 nn 和接下来给出边信息的条数 mm。
接下来 mm 行,每行三个整数 u, v, wu,v,w。
- 若 w \geq 0w≥0,则表示存在一条从 uu 至 vv 边权为 ww 的边,还存在一条从 vv 至 uu 边权为 ww 的边。
- 若 w < 0w<0,则只表示存在一条从 uu 至 vv 边权为 ww 的边。
输出格式
对于每组数据,输出一行一个字符串,若所求负环存在,则输出 YES
,否则输出 NO
。
输入输出样例
输入
2 3 4 1 2 2 1 3 4 2 3 1 3 1 -3 3 3 1 2 3 2 3 4 3 1 -8
输出
NO YES
说明/提示
数据规模与约定
对于全部的测试点,保证:
- 1 \leq n \leq 2 \times 10^31≤n≤2×103,1 \leq m \leq 3 \times 10^31≤m≤3×103。
- 1 \leq u, v \leq n1≤u,v≤n,-10^4 \leq w \leq 10^4−104≤w≤104。
- 1 \leq T \leq 101≤T≤10。
提示
请注意,mm 不是图的边数。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
int st[N],cnt[N],dist[N],t,n,m,p[N];
int h[N],e[N],w[N],ne[N],idx;
queue<int>q,temp;
void init()
{
q=temp;
idx=0;
memset(h,-1,sizeof h);
memset(st,0,sizeof st);
memset(cnt,0,sizeof cnt);
memset(dist,0x3f,sizeof dist);
for(int i=1;i<=n;i++) p[i]=i;
}
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
void add(int a,int b,int c) {e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;}
bool spfa()
{
q.push(1),st[1]=1,dist[1]=0;
while(q.size())
{
int u=q.front(); q.pop();
st[u]=false;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[u]+w[i])
{
dist[j]=dist[u]+w[i];
cnt[j]=cnt[u]+1;
if(cnt[j]>=n) return true;
if(!st[j]) q.push(j),st[j]=1;
}
}
}
return false;
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
init();
for(int i=0;i<m;i++)
{
int a,b,c; cin>>a>>b>>c;
if(c>=0) add(a,b,c),add(b,a,c);
else add(a,b,c);
}
if(spfa()) puts("YES");
else puts("NO");
}
return 0;
}
题目描述
给出两个字符串 s_1s1 和 s_2s2,若 s_1s1 的区间 [l, r][l,r] 子串与 s_2s2 完全相同,则称 s_2s2 在 s_1s1 中出现了,其出现位置为 ll。
现在请你求出 s_2s2 在 s_1s1 中所有出现的位置。
定义一个字符串 ss 的 border 为 ss 的一个非 ss 本身的子串 tt,满足 tt 既是 ss 的前缀,又是 ss 的后缀。
对于 s_2s2,你还需要求出对于其每个前缀 s's′ 的最长 border t't′ 的长度。
输入格式
第一行为一个字符串,即为 s_1s1。
第二行为一个字符串,即为 s_2s2。
输出格式
首先输出若干行,每行一个整数,按从小到大的顺序输出 s_2s2 在 s_1s1 中出现的位置。
最后一行输出 |s_2|∣s2∣ 个整数,第 ii 个整数表示 s_2s2 的长度为 ii 的前缀的最长 border 长度。
输入输出样例
输入
ABABABC ABA
输出
1 3 0 0 1
说明/提示
样例 1 解释
。
对于 s_2s2 长度为 33 的前缀 ABA
,字符串 A
既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 11。
数据规模与约定
本题采用多测试点捆绑测试,共有 3 个子任务。
- Subtask 1(30 points):|s_1| \leq 15∣s1∣≤15,|s_2| \leq 5∣s2∣≤5。
- Subtask 2(40 points):|s_1| \leq 10^4∣s1∣≤104,|s_2| \leq 10^2∣s2∣≤102。
- Subtask 3(30 points):无特殊约定。
对于全部的测试点,保证 1 \leq |s_1|,|s_2| \leq 10^61≤∣s1∣,∣s2∣≤106,s_1, s_2s1,s2 中均只含大写英文字母
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
int next[1000005];
string s,p;
void getnext(string s)
{
int j=0;//初始化
next[0]=0;
for(int i=1;i<s.length();i++)
{
while(j>0&&s[i]!=s[j]) j=next[j-1];//向前移一位//处理前后缀不相同
if(s[j]==s[i]) j++;//向后移一位//处理前后缀相同
next[i]=j;//更新next 数组
}
}
void kmp(string s,string p)
{
int j=0;//j可以看做表示当前已经匹配完的模式串的最后一位的位置
for(int i=0;i<s.length();i++)
{
while(j>0&&p[j]!=s[i]) j=next[j-1]; //如果失配 ,那么就向回跳
if (p[j]==s[i]) j++;//匹配成功,向后继续
if (j==p.length())
{
cout<<i+1-p.length()+1<<endl;
j=next[j-1];//继续匹配
}
}
return ;
}
int main()
{
cin>>s>>p;
getnext(p);
kmp(s,p);
for(int i=0;i<p.length();i++)
{
cout<<next[i]<<' ';
}
return 0;
}